mirror of
https://github.com/adulau/aha.git
synced 2024-12-28 03:36:19 +00:00
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: (21 commits) USB: musb: fix srp sysfs entry deletion USB: musb: resume suspended root hub on disconnect USB: musb: use right poll limit for low speed devices USB: musb: be careful with 64K+ transfer lengths, host side USB: musb: fix data toggle saving with shared FIFO USB: musb: host endpoint_disable() oops fixes USB: musb: fix urb_dequeue() method USB: musb: fix musb_host_tx() for shared endpoint FIFO USB: musb: be careful with 64K+ transfer lengths (gadget side) usb: musb: make Davinci *work* in mainline USB: usb_get_string should check the descriptor type USB: gadget: fix build error in omap_apollon_2420_defconfig USB: g_file_storage: automatically disable stalls under Atmel USB: usb-storage: add IGNORE_RESIDUE flag for Genesys Logic adapters USB: Quirk for Hummingbird huc56s / Conexant ACM modem USB: serial: add support for second revision of Ericsson F3507G WWAN card USB: cdc-acm: add usb id for motomagx phones USB: option: add BenQ 3g modem information usb: gadget: obex: select correct ep descriptors USB: EHCI: slow down ITD reuse ...
This commit is contained in:
commit
3c4f1158cd
19 changed files with 176 additions and 75 deletions
|
@ -311,6 +311,9 @@ evm_u35_setup(struct i2c_client *client, int gpio, unsigned ngpio, void *c)
|
|||
gpio_request(gpio + 7, "nCF_SEL");
|
||||
gpio_direction_output(gpio + 7, 1);
|
||||
|
||||
/* irlml6401 sustains over 3A, switches 5V in under 8 msec */
|
||||
setup_usb(500, 8);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -417,9 +420,6 @@ static __init void davinci_evm_init(void)
|
|||
platform_add_devices(davinci_evm_devices,
|
||||
ARRAY_SIZE(davinci_evm_devices));
|
||||
evm_init_i2c();
|
||||
|
||||
/* irlml6401 sustains over 3A, switches 5V in under 8 msec */
|
||||
setup_usb(500, 8);
|
||||
}
|
||||
|
||||
static __init void davinci_evm_irq_init(void)
|
||||
|
|
|
@ -230,6 +230,11 @@ static struct clk davinci_clks[] = {
|
|||
.rate = &commonrate,
|
||||
.lpsc = DAVINCI_LPSC_GPIO,
|
||||
},
|
||||
{
|
||||
.name = "usb",
|
||||
.rate = &commonrate,
|
||||
.lpsc = DAVINCI_LPSC_USB,
|
||||
},
|
||||
{
|
||||
.name = "AEMIFCLK",
|
||||
.rate = &commonrate,
|
||||
|
|
|
@ -47,6 +47,7 @@ static struct musb_hdrc_platform_data usb_data = {
|
|||
#elif defined(CONFIG_USB_MUSB_HOST)
|
||||
.mode = MUSB_HOST,
|
||||
#endif
|
||||
.clock = "usb",
|
||||
.config = &musb_config,
|
||||
};
|
||||
|
||||
|
|
|
@ -1376,6 +1376,15 @@ static struct usb_device_id acm_ids[] = {
|
|||
{ USB_DEVICE(0x0572, 0x1324), /* Conexant USB MODEM RD02-D400 */
|
||||
.driver_info = NO_UNION_NORMAL, /* has no union descriptor */
|
||||
},
|
||||
{ USB_DEVICE(0x22b8, 0x6425), /* Motorola MOTOMAGX phones */
|
||||
},
|
||||
{ USB_DEVICE(0x0572, 0x1329), /* Hummingbird huc56s (Conexant) */
|
||||
.driver_info = NO_UNION_NORMAL, /* union descriptor misplaced on
|
||||
data interface instead of
|
||||
communications interface.
|
||||
Maybe we should define a new
|
||||
quirk for this. */
|
||||
},
|
||||
|
||||
/* control interfaces with various AT-command sets */
|
||||
{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
|
||||
|
|
|
@ -653,7 +653,7 @@ int usb_get_descriptor(struct usb_device *dev, unsigned char type,
|
|||
if (result <= 0 && result != -ETIMEDOUT)
|
||||
continue;
|
||||
if (result > 1 && ((u8 *)buf)[1] != type) {
|
||||
result = -EPROTO;
|
||||
result = -ENODATA;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
@ -696,8 +696,13 @@ static int usb_get_string(struct usb_device *dev, unsigned short langid,
|
|||
USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
|
||||
(USB_DT_STRING << 8) + index, langid, buf, size,
|
||||
USB_CTRL_GET_TIMEOUT);
|
||||
if (!(result == 0 || result == -EPIPE))
|
||||
break;
|
||||
if (result == 0 || result == -EPIPE)
|
||||
continue;
|
||||
if (result > 1 && ((u8 *) buf)[1] != USB_DT_STRING) {
|
||||
result = -ENODATA;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -191,6 +191,7 @@ config USB_GADGET_OMAP
|
|||
boolean "OMAP USB Device Controller"
|
||||
depends on ARCH_OMAP
|
||||
select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_H4_OTG
|
||||
select USB_OTG_UTILS if ARCH_OMAP
|
||||
help
|
||||
Many Texas Instruments OMAP processors have flexible full
|
||||
speed USB device controllers, with support for up to 30
|
||||
|
|
|
@ -366,9 +366,9 @@ obex_bind(struct usb_configuration *c, struct usb_function *f)
|
|||
f->hs_descriptors = usb_copy_descriptors(hs_function);
|
||||
|
||||
obex->hs.obex_in = usb_find_endpoint(hs_function,
|
||||
f->descriptors, &obex_hs_ep_in_desc);
|
||||
f->hs_descriptors, &obex_hs_ep_in_desc);
|
||||
obex->hs.obex_out = usb_find_endpoint(hs_function,
|
||||
f->descriptors, &obex_hs_ep_out_desc);
|
||||
f->hs_descriptors, &obex_hs_ep_out_desc);
|
||||
}
|
||||
|
||||
/* Avoid letting this gadget enumerate until the userspace
|
||||
|
|
|
@ -3879,7 +3879,11 @@ static int __init check_parameters(struct fsg_dev *fsg)
|
|||
mod_data.protocol_type = USB_SC_SCSI;
|
||||
mod_data.protocol_name = "Transparent SCSI";
|
||||
|
||||
if (gadget_is_sh(fsg->gadget))
|
||||
/* Some peripheral controllers are known not to be able to
|
||||
* halt bulk endpoints correctly. If one of them is present,
|
||||
* disable stalls.
|
||||
*/
|
||||
if (gadget_is_sh(fsg->gadget) || gadget_is_at91(fsg->gadget))
|
||||
mod_data.can_stall = 0;
|
||||
|
||||
if (mod_data.release == 0xffff) { // Parameter wasn't set
|
||||
|
|
|
@ -404,7 +404,10 @@ static void struct_ep_qh_setup(struct fsl_udc *udc, unsigned char ep_num,
|
|||
}
|
||||
if (zlt)
|
||||
tmp |= EP_QUEUE_HEAD_ZLT_SEL;
|
||||
|
||||
p_QH->max_pkt_length = cpu_to_le32(tmp);
|
||||
p_QH->next_dtd_ptr = 1;
|
||||
p_QH->size_ioc_int_sts = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -485,6 +485,7 @@ static int ehci_init(struct usb_hcd *hcd)
|
|||
* periodic_size can shrink by USBCMD update if hcc_params allows.
|
||||
*/
|
||||
ehci->periodic_size = DEFAULT_I_TDPS;
|
||||
INIT_LIST_HEAD(&ehci->cached_itd_list);
|
||||
if ((retval = ehci_mem_init(ehci, GFP_KERNEL)) < 0)
|
||||
return retval;
|
||||
|
||||
|
@ -497,6 +498,7 @@ static int ehci_init(struct usb_hcd *hcd)
|
|||
|
||||
ehci->reclaim = NULL;
|
||||
ehci->next_uframe = -1;
|
||||
ehci->clock_frame = -1;
|
||||
|
||||
/*
|
||||
* dedicate a qh for the async ring head, since we couldn't unlink
|
||||
|
|
|
@ -128,6 +128,7 @@ static inline void qh_put (struct ehci_qh *qh)
|
|||
|
||||
static void ehci_mem_cleanup (struct ehci_hcd *ehci)
|
||||
{
|
||||
free_cached_itd_list(ehci);
|
||||
if (ehci->async)
|
||||
qh_put (ehci->async);
|
||||
ehci->async = NULL;
|
||||
|
|
|
@ -1004,7 +1004,8 @@ iso_stream_put(struct ehci_hcd *ehci, struct ehci_iso_stream *stream)
|
|||
|
||||
is_in = (stream->bEndpointAddress & USB_DIR_IN) ? 0x10 : 0;
|
||||
stream->bEndpointAddress &= 0x0f;
|
||||
stream->ep->hcpriv = NULL;
|
||||
if (stream->ep)
|
||||
stream->ep->hcpriv = NULL;
|
||||
|
||||
if (stream->rescheduled) {
|
||||
ehci_info (ehci, "ep%d%s-iso rescheduled "
|
||||
|
@ -1653,14 +1654,28 @@ itd_complete (
|
|||
(stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out");
|
||||
}
|
||||
iso_stream_put (ehci, stream);
|
||||
/* OK to recycle this ITD now that its completion callback ran. */
|
||||
|
||||
done:
|
||||
usb_put_urb(urb);
|
||||
itd->urb = NULL;
|
||||
itd->stream = NULL;
|
||||
list_move(&itd->itd_list, &stream->free_list);
|
||||
iso_stream_put(ehci, stream);
|
||||
|
||||
if (ehci->clock_frame != itd->frame || itd->index[7] != -1) {
|
||||
/* OK to recycle this ITD now. */
|
||||
itd->stream = NULL;
|
||||
list_move(&itd->itd_list, &stream->free_list);
|
||||
iso_stream_put(ehci, stream);
|
||||
} else {
|
||||
/* HW might remember this ITD, so we can't recycle it yet.
|
||||
* Move it to a safe place until a new frame starts.
|
||||
*/
|
||||
list_move(&itd->itd_list, &ehci->cached_itd_list);
|
||||
if (stream->refcount == 2) {
|
||||
/* If iso_stream_put() were called here, stream
|
||||
* would be freed. Instead, just prevent reuse.
|
||||
*/
|
||||
stream->ep->hcpriv = NULL;
|
||||
stream->ep = NULL;
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -2101,6 +2116,20 @@ done:
|
|||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static void free_cached_itd_list(struct ehci_hcd *ehci)
|
||||
{
|
||||
struct ehci_itd *itd, *n;
|
||||
|
||||
list_for_each_entry_safe(itd, n, &ehci->cached_itd_list, itd_list) {
|
||||
struct ehci_iso_stream *stream = itd->stream;
|
||||
itd->stream = NULL;
|
||||
list_move(&itd->itd_list, &stream->free_list);
|
||||
iso_stream_put(ehci, stream);
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static void
|
||||
scan_periodic (struct ehci_hcd *ehci)
|
||||
{
|
||||
|
@ -2115,10 +2144,17 @@ scan_periodic (struct ehci_hcd *ehci)
|
|||
* Touches as few pages as possible: cache-friendly.
|
||||
*/
|
||||
now_uframe = ehci->next_uframe;
|
||||
if (HC_IS_RUNNING (ehci_to_hcd(ehci)->state))
|
||||
if (HC_IS_RUNNING(ehci_to_hcd(ehci)->state)) {
|
||||
clock = ehci_readl(ehci, &ehci->regs->frame_index);
|
||||
else
|
||||
clock_frame = (clock >> 3) % ehci->periodic_size;
|
||||
} else {
|
||||
clock = now_uframe + mod - 1;
|
||||
clock_frame = -1;
|
||||
}
|
||||
if (ehci->clock_frame != clock_frame) {
|
||||
free_cached_itd_list(ehci);
|
||||
ehci->clock_frame = clock_frame;
|
||||
}
|
||||
clock %= mod;
|
||||
clock_frame = clock >> 3;
|
||||
|
||||
|
@ -2277,6 +2313,10 @@ restart:
|
|||
/* rescan the rest of this frame, then ... */
|
||||
clock = now;
|
||||
clock_frame = clock >> 3;
|
||||
if (ehci->clock_frame != clock_frame) {
|
||||
free_cached_itd_list(ehci);
|
||||
ehci->clock_frame = clock_frame;
|
||||
}
|
||||
} else {
|
||||
now_uframe++;
|
||||
now_uframe %= mod;
|
||||
|
|
|
@ -87,6 +87,10 @@ struct ehci_hcd { /* one per controller */
|
|||
int next_uframe; /* scan periodic, start here */
|
||||
unsigned periodic_sched; /* periodic activity count */
|
||||
|
||||
/* list of itds completed while clock_frame was still active */
|
||||
struct list_head cached_itd_list;
|
||||
unsigned clock_frame;
|
||||
|
||||
/* per root hub port */
|
||||
unsigned long reset_done [EHCI_MAX_ROOT_PORTS];
|
||||
|
||||
|
@ -220,6 +224,8 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action)
|
|||
}
|
||||
}
|
||||
|
||||
static void free_cached_itd_list(struct ehci_hcd *ehci);
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
#include <linux/usb/ehci_def.h>
|
||||
|
|
|
@ -377,18 +377,8 @@ int __init musb_platform_init(struct musb *musb)
|
|||
u32 revision;
|
||||
|
||||
musb->mregs += DAVINCI_BASE_OFFSET;
|
||||
#if 0
|
||||
/* REVISIT there's something odd about clocking, this
|
||||
* didn't appear do the job ...
|
||||
*/
|
||||
musb->clock = clk_get(pDevice, "usb");
|
||||
if (IS_ERR(musb->clock))
|
||||
return PTR_ERR(musb->clock);
|
||||
|
||||
status = clk_enable(musb->clock);
|
||||
if (status < 0)
|
||||
return -ENODEV;
|
||||
#endif
|
||||
clk_enable(musb->clock);
|
||||
|
||||
/* returns zero if e.g. not clocked */
|
||||
revision = musb_readl(tibase, DAVINCI_USB_VERSION_REG);
|
||||
|
@ -453,5 +443,8 @@ int musb_platform_exit(struct musb *musb)
|
|||
}
|
||||
|
||||
phy_off();
|
||||
|
||||
clk_disable(musb->clock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -115,7 +115,7 @@
|
|||
|
||||
|
||||
unsigned musb_debug;
|
||||
module_param(musb_debug, uint, S_IRUGO | S_IWUSR);
|
||||
module_param_named(debug, musb_debug, uint, S_IRUGO | S_IWUSR);
|
||||
MODULE_PARM_DESC(debug, "Debug message level. Default = 0");
|
||||
|
||||
#define DRIVER_AUTHOR "Mentor Graphics, Texas Instruments, Nokia"
|
||||
|
@ -767,6 +767,7 @@ static irqreturn_t musb_stage2_irq(struct musb *musb, u8 int_usb,
|
|||
#ifdef CONFIG_USB_MUSB_HDRC_HCD
|
||||
case OTG_STATE_A_HOST:
|
||||
case OTG_STATE_A_SUSPEND:
|
||||
usb_hcd_resume_root_hub(musb_to_hcd(musb));
|
||||
musb_root_disconnect(musb);
|
||||
if (musb->a_wait_bcon != 0)
|
||||
musb_platform_try_idle(musb, jiffies
|
||||
|
@ -1815,7 +1816,7 @@ static void musb_free(struct musb *musb)
|
|||
#ifdef CONFIG_SYSFS
|
||||
device_remove_file(musb->controller, &dev_attr_mode);
|
||||
device_remove_file(musb->controller, &dev_attr_vbus);
|
||||
#ifdef CONFIG_USB_MUSB_OTG
|
||||
#ifdef CONFIG_USB_GADGET_MUSB_HDRC
|
||||
device_remove_file(musb->controller, &dev_attr_srp);
|
||||
#endif
|
||||
#endif
|
||||
|
@ -2063,7 +2064,7 @@ fail2:
|
|||
#ifdef CONFIG_SYSFS
|
||||
device_remove_file(musb->controller, &dev_attr_mode);
|
||||
device_remove_file(musb->controller, &dev_attr_vbus);
|
||||
#ifdef CONFIG_USB_MUSB_OTG
|
||||
#ifdef CONFIG_USB_GADGET_MUSB_HDRC
|
||||
device_remove_file(musb->controller, &dev_attr_srp);
|
||||
#endif
|
||||
#endif
|
||||
|
@ -2243,10 +2244,10 @@ static int __init musb_init(void)
|
|||
return platform_driver_probe(&musb_driver, musb_probe);
|
||||
}
|
||||
|
||||
/* make us init after usbcore and before usb
|
||||
* gadget and host-side drivers start to register
|
||||
/* make us init after usbcore and i2c (transceivers, regulators, etc)
|
||||
* and before usb gadget and host-side drivers start to register
|
||||
*/
|
||||
subsys_initcall(musb_init);
|
||||
fs_initcall(musb_init);
|
||||
|
||||
static void __exit musb_cleanup(void)
|
||||
{
|
||||
|
|
|
@ -575,7 +575,7 @@ static void rxstate(struct musb *musb, struct musb_request *req)
|
|||
struct usb_request *request = &req->request;
|
||||
struct musb_ep *musb_ep = &musb->endpoints[epnum].ep_out;
|
||||
void __iomem *epio = musb->endpoints[epnum].regs;
|
||||
u16 fifo_count = 0;
|
||||
unsigned fifo_count = 0;
|
||||
u16 len = musb_ep->packet_sz;
|
||||
|
||||
csr = musb_readw(epio, MUSB_RXCSR);
|
||||
|
@ -687,7 +687,7 @@ static void rxstate(struct musb *musb, struct musb_request *req)
|
|||
len, fifo_count,
|
||||
musb_ep->packet_sz);
|
||||
|
||||
fifo_count = min(len, fifo_count);
|
||||
fifo_count = min_t(unsigned, len, fifo_count);
|
||||
|
||||
#ifdef CONFIG_USB_TUSB_OMAP_DMA
|
||||
if (tusb_dma_omap() && musb_ep->dma) {
|
||||
|
|
|
@ -335,16 +335,11 @@ musb_save_toggle(struct musb_hw_ep *ep, int is_in, struct urb *urb)
|
|||
static struct musb_qh *
|
||||
musb_giveback(struct musb_qh *qh, struct urb *urb, int status)
|
||||
{
|
||||
int is_in;
|
||||
struct musb_hw_ep *ep = qh->hw_ep;
|
||||
struct musb *musb = ep->musb;
|
||||
int is_in = usb_pipein(urb->pipe);
|
||||
int ready = qh->is_ready;
|
||||
|
||||
if (ep->is_shared_fifo)
|
||||
is_in = 1;
|
||||
else
|
||||
is_in = usb_pipein(urb->pipe);
|
||||
|
||||
/* save toggle eagerly, for paranoia */
|
||||
switch (qh->type) {
|
||||
case USB_ENDPOINT_XFER_BULK:
|
||||
|
@ -432,7 +427,7 @@ musb_advance_schedule(struct musb *musb, struct urb *urb,
|
|||
else
|
||||
qh = musb_giveback(qh, urb, urb->status);
|
||||
|
||||
if (qh && qh->is_ready && !list_empty(&qh->hep->urb_list)) {
|
||||
if (qh != NULL && qh->is_ready) {
|
||||
DBG(4, "... next ep%d %cX urb %p\n",
|
||||
hw_ep->epnum, is_in ? 'R' : 'T',
|
||||
next_urb(qh));
|
||||
|
@ -942,8 +937,8 @@ static bool musb_h_ep0_continue(struct musb *musb, u16 len, struct urb *urb)
|
|||
switch (musb->ep0_stage) {
|
||||
case MUSB_EP0_IN:
|
||||
fifo_dest = urb->transfer_buffer + urb->actual_length;
|
||||
fifo_count = min(len, ((u16) (urb->transfer_buffer_length
|
||||
- urb->actual_length)));
|
||||
fifo_count = min_t(size_t, len, urb->transfer_buffer_length -
|
||||
urb->actual_length);
|
||||
if (fifo_count < len)
|
||||
urb->status = -EOVERFLOW;
|
||||
|
||||
|
@ -976,10 +971,9 @@ static bool musb_h_ep0_continue(struct musb *musb, u16 len, struct urb *urb)
|
|||
}
|
||||
/* FALLTHROUGH */
|
||||
case MUSB_EP0_OUT:
|
||||
fifo_count = min(qh->maxpacket, ((u16)
|
||||
(urb->transfer_buffer_length
|
||||
- urb->actual_length)));
|
||||
|
||||
fifo_count = min_t(size_t, qh->maxpacket,
|
||||
urb->transfer_buffer_length -
|
||||
urb->actual_length);
|
||||
if (fifo_count) {
|
||||
fifo_dest = (u8 *) (urb->transfer_buffer
|
||||
+ urb->actual_length);
|
||||
|
@ -1161,7 +1155,8 @@ void musb_host_tx(struct musb *musb, u8 epnum)
|
|||
struct urb *urb;
|
||||
struct musb_hw_ep *hw_ep = musb->endpoints + epnum;
|
||||
void __iomem *epio = hw_ep->regs;
|
||||
struct musb_qh *qh = hw_ep->out_qh;
|
||||
struct musb_qh *qh = hw_ep->is_shared_fifo ? hw_ep->in_qh
|
||||
: hw_ep->out_qh;
|
||||
u32 status = 0;
|
||||
void __iomem *mbase = musb->mregs;
|
||||
struct dma_channel *dma;
|
||||
|
@ -1308,7 +1303,8 @@ void musb_host_tx(struct musb *musb, u8 epnum)
|
|||
* packets before updating TXCSR ... other docs disagree ...
|
||||
*/
|
||||
/* PIO: start next packet in this URB */
|
||||
wLength = min(qh->maxpacket, (u16) wLength);
|
||||
if (wLength > qh->maxpacket)
|
||||
wLength = qh->maxpacket;
|
||||
musb_write_fifo(hw_ep, wLength, buf);
|
||||
qh->segsize = wLength;
|
||||
|
||||
|
@ -1867,19 +1863,21 @@ static int musb_urb_enqueue(
|
|||
}
|
||||
qh->type_reg = type_reg;
|
||||
|
||||
/* precompute rxinterval/txinterval register */
|
||||
interval = min((u8)16, epd->bInterval); /* log encoding */
|
||||
/* Precompute RXINTERVAL/TXINTERVAL register */
|
||||
switch (qh->type) {
|
||||
case USB_ENDPOINT_XFER_INT:
|
||||
/* fullspeed uses linear encoding */
|
||||
if (USB_SPEED_FULL == urb->dev->speed) {
|
||||
interval = epd->bInterval;
|
||||
if (!interval)
|
||||
interval = 1;
|
||||
/*
|
||||
* Full/low speeds use the linear encoding,
|
||||
* high speed uses the logarithmic encoding.
|
||||
*/
|
||||
if (urb->dev->speed <= USB_SPEED_FULL) {
|
||||
interval = max_t(u8, epd->bInterval, 1);
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case USB_ENDPOINT_XFER_ISOC:
|
||||
/* iso always uses log encoding */
|
||||
/* ISO always uses logarithmic encoding */
|
||||
interval = min_t(u8, epd->bInterval, 16);
|
||||
break;
|
||||
default:
|
||||
/* REVISIT we actually want to use NAK limits, hinting to the
|
||||
|
@ -2037,9 +2035,9 @@ static int musb_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
|
|||
goto done;
|
||||
|
||||
/* Any URB not actively programmed into endpoint hardware can be
|
||||
* immediately given back. Such an URB must be at the head of its
|
||||
* immediately given back; that's any URB not at the head of an
|
||||
* endpoint queue, unless someday we get real DMA queues. And even
|
||||
* then, it might not be known to the hardware...
|
||||
* if it's at the head, it might not be known to the hardware...
|
||||
*
|
||||
* Otherwise abort current transfer, pending dma, etc.; urb->status
|
||||
* has already been updated. This is a synchronous abort; it'd be
|
||||
|
@ -2078,6 +2076,15 @@ static int musb_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
|
|||
qh->is_ready = 0;
|
||||
__musb_giveback(musb, urb, 0);
|
||||
qh->is_ready = ready;
|
||||
|
||||
/* If nothing else (usually musb_giveback) is using it
|
||||
* and its URB list has emptied, recycle this qh.
|
||||
*/
|
||||
if (ready && list_empty(&qh->hep->urb_list)) {
|
||||
qh->hep->hcpriv = NULL;
|
||||
list_del(&qh->ring);
|
||||
kfree(qh);
|
||||
}
|
||||
} else
|
||||
ret = musb_cleanup_urb(urb, qh, urb->pipe & USB_DIR_IN);
|
||||
done:
|
||||
|
@ -2093,15 +2100,16 @@ musb_h_disable(struct usb_hcd *hcd, struct usb_host_endpoint *hep)
|
|||
unsigned long flags;
|
||||
struct musb *musb = hcd_to_musb(hcd);
|
||||
u8 is_in = epnum & USB_DIR_IN;
|
||||
struct musb_qh *qh = hep->hcpriv;
|
||||
struct urb *urb, *tmp;
|
||||
struct musb_qh *qh;
|
||||
struct urb *urb;
|
||||
struct list_head *sched;
|
||||
|
||||
if (!qh)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&musb->lock, flags);
|
||||
|
||||
qh = hep->hcpriv;
|
||||
if (qh == NULL)
|
||||
goto exit;
|
||||
|
||||
switch (qh->type) {
|
||||
case USB_ENDPOINT_XFER_CONTROL:
|
||||
sched = &musb->control;
|
||||
|
@ -2135,13 +2143,28 @@ musb_h_disable(struct usb_hcd *hcd, struct usb_host_endpoint *hep)
|
|||
|
||||
/* cleanup */
|
||||
musb_cleanup_urb(urb, qh, urb->pipe & USB_DIR_IN);
|
||||
} else
|
||||
urb = NULL;
|
||||
|
||||
/* then just nuke all the others */
|
||||
list_for_each_entry_safe_from(urb, tmp, &hep->urb_list, urb_list)
|
||||
musb_giveback(qh, urb, -ESHUTDOWN);
|
||||
/* Then nuke all the others ... and advance the
|
||||
* queue on hw_ep (e.g. bulk ring) when we're done.
|
||||
*/
|
||||
while (!list_empty(&hep->urb_list)) {
|
||||
urb = next_urb(qh);
|
||||
urb->status = -ESHUTDOWN;
|
||||
musb_advance_schedule(musb, urb, qh->hw_ep, is_in);
|
||||
}
|
||||
} else {
|
||||
/* Just empty the queue; the hardware is busy with
|
||||
* other transfers, and since !qh->is_ready nothing
|
||||
* will activate any of these as it advances.
|
||||
*/
|
||||
while (!list_empty(&hep->urb_list))
|
||||
__musb_giveback(musb, next_urb(qh), -ESHUTDOWN);
|
||||
|
||||
hep->hcpriv = NULL;
|
||||
list_del(&qh->ring);
|
||||
kfree(qh);
|
||||
}
|
||||
exit:
|
||||
spin_unlock_irqrestore(&musb->lock, flags);
|
||||
}
|
||||
|
||||
|
|
|
@ -294,7 +294,11 @@ static int option_send_setup(struct tty_struct *tty, struct usb_serial_port *po
|
|||
|
||||
/* Ericsson products */
|
||||
#define ERICSSON_VENDOR_ID 0x0bdb
|
||||
#define ERICSSON_PRODUCT_F3507G 0x1900
|
||||
#define ERICSSON_PRODUCT_F3507G_1 0x1900
|
||||
#define ERICSSON_PRODUCT_F3507G_2 0x1902
|
||||
|
||||
#define BENQ_VENDOR_ID 0x04a5
|
||||
#define BENQ_PRODUCT_H10 0x4068
|
||||
|
||||
static struct usb_device_id option_ids[] = {
|
||||
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
|
||||
|
@ -509,7 +513,10 @@ static struct usb_device_id option_ids[] = {
|
|||
{ USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF626) },
|
||||
{ USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF628) },
|
||||
{ USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH) },
|
||||
{ USB_DEVICE(ERICSSON_VENDOR_ID, ERICSSON_PRODUCT_F3507G) },
|
||||
{ USB_DEVICE(ERICSSON_VENDOR_ID, ERICSSON_PRODUCT_F3507G_1) },
|
||||
{ USB_DEVICE(ERICSSON_VENDOR_ID, ERICSSON_PRODUCT_F3507G_2) },
|
||||
{ USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) },
|
||||
{ USB_DEVICE(0x1da5, 0x4515) }, /* BenQ H20 */
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, option_ids);
|
||||
|
|
|
@ -907,13 +907,13 @@ UNUSUAL_DEV( 0x05e3, 0x0701, 0x0000, 0xffff,
|
|||
"Genesys Logic",
|
||||
"USB to IDE Optical",
|
||||
US_SC_DEVICE, US_PR_DEVICE, NULL,
|
||||
US_FL_GO_SLOW | US_FL_MAX_SECTORS_64 ),
|
||||
US_FL_GO_SLOW | US_FL_MAX_SECTORS_64 | US_FL_IGNORE_RESIDUE ),
|
||||
|
||||
UNUSUAL_DEV( 0x05e3, 0x0702, 0x0000, 0xffff,
|
||||
"Genesys Logic",
|
||||
"USB to IDE Disk",
|
||||
US_SC_DEVICE, US_PR_DEVICE, NULL,
|
||||
US_FL_GO_SLOW | US_FL_MAX_SECTORS_64 ),
|
||||
US_FL_GO_SLOW | US_FL_MAX_SECTORS_64 | US_FL_IGNORE_RESIDUE ),
|
||||
|
||||
/* Reported by Ben Efros <ben@pc-doctor.com> */
|
||||
UNUSUAL_DEV( 0x05e3, 0x0723, 0x9451, 0x9451,
|
||||
|
|
Loading…
Reference in a new issue