Commit 00dad7fa authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'usb-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6

* 'usb-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6: (28 commits)
  Revert "USB: xhci: Use GFP_ATOMIC under spin_lock"
  USB: ohci-jz4740: Fix spelling in MODULE_ALIAS
  UWB: Return UWB_RSV_ALLOC_NOT_FOUND rather than crashing on NULL dereference if kzalloc fails
  usb: core: fix information leak to userland
  usb: misc: iowarrior: fix information leak to userland
  usb: misc: sisusbvga: fix information leak to userland
  usb: subtle increased memory usage in u_serial
  USB: option: fix when the driver is loaded incorrectly for some Huawei devices.
  USB: xhci: Use GFP_ATOMIC under spin_lock
  usb: gadget: goku_udc: add registered flag bit, fixing build
  USB: ehci/mxc: compile fix
  USB: Fix FSL USB driver on non Open Firmware systems
  USB: the development of the usb tree is now in git
  usb: musb: fail unaligned DMA transfers on v1.8 and above
  USB: ftdi_sio: add device IDs for Milkymist One JTAG/serial
  usb.h: fix ioctl kernel-doc info
  usb: musb: gadget: kill duplicate code in musb_gadget_queue()
  usb: musb: Fix handling of spurious SESSREQ
  usb: musb: fix kernel oops when loading musb_hdrc module for the 2nd time
  USB: musb: blackfin: push clkin value to platform resources
  ...
parents edaa4d66 86871975
...@@ -6233,7 +6233,7 @@ USB SUBSYSTEM ...@@ -6233,7 +6233,7 @@ USB SUBSYSTEM
M: Greg Kroah-Hartman <gregkh@suse.de> M: Greg Kroah-Hartman <gregkh@suse.de>
L: linux-usb@vger.kernel.org L: linux-usb@vger.kernel.org
W: http://www.linux-usb.org W: http://www.linux-usb.org
T: quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6.git
S: Supported S: Supported
F: Documentation/usb/ F: Documentation/usb/
F: drivers/net/usb/ F: drivers/net/usb/
......
...@@ -965,10 +965,11 @@ static int proc_getdriver(struct dev_state *ps, void __user *arg) ...@@ -965,10 +965,11 @@ static int proc_getdriver(struct dev_state *ps, void __user *arg)
static int proc_connectinfo(struct dev_state *ps, void __user *arg) static int proc_connectinfo(struct dev_state *ps, void __user *arg)
{ {
struct usbdevfs_connectinfo ci; struct usbdevfs_connectinfo ci = {
.devnum = ps->dev->devnum,
.slow = ps->dev->speed == USB_SPEED_LOW
};
ci.devnum = ps->dev->devnum;
ci.slow = ps->dev->speed == USB_SPEED_LOW;
if (copy_to_user(arg, &ci, sizeof(ci))) if (copy_to_user(arg, &ci, sizeof(ci)))
return -EFAULT; return -EFAULT;
return 0; return 0;
......
...@@ -158,7 +158,7 @@ config USB_GADGET_FSL_USB2 ...@@ -158,7 +158,7 @@ config USB_GADGET_FSL_USB2
boolean "Freescale Highspeed USB DR Peripheral Controller" boolean "Freescale Highspeed USB DR Peripheral Controller"
depends on FSL_SOC || ARCH_MXC depends on FSL_SOC || ARCH_MXC
select USB_GADGET_DUALSPEED select USB_GADGET_DUALSPEED
select USB_FSL_MPH_DR_OF select USB_FSL_MPH_DR_OF if OF
help help
Some of Freescale PowerPC processors have a High Speed Some of Freescale PowerPC processors have a High Speed
Dual-Role(DR) USB controller, which supports device mode. Dual-Role(DR) USB controller, which supports device mode.
......
...@@ -251,7 +251,8 @@ struct goku_udc { ...@@ -251,7 +251,8 @@ struct goku_udc {
got_region:1, got_region:1,
req_config:1, req_config:1,
configured:1, configured:1,
enabled:1; enabled:1,
registered:1;
/* pci state used to access those endpoints */ /* pci state used to access those endpoints */
struct pci_dev *pdev; struct pci_dev *pdev;
......
...@@ -105,11 +105,15 @@ struct gs_port { ...@@ -105,11 +105,15 @@ struct gs_port {
wait_queue_head_t close_wait; /* wait for last close */ wait_queue_head_t close_wait; /* wait for last close */
struct list_head read_pool; struct list_head read_pool;
int read_started;
int read_allocated;
struct list_head read_queue; struct list_head read_queue;
unsigned n_read; unsigned n_read;
struct tasklet_struct push; struct tasklet_struct push;
struct list_head write_pool; struct list_head write_pool;
int write_started;
int write_allocated;
struct gs_buf port_write_buf; struct gs_buf port_write_buf;
wait_queue_head_t drain_wait; /* wait while writes drain */ wait_queue_head_t drain_wait; /* wait while writes drain */
...@@ -363,6 +367,9 @@ __acquires(&port->port_lock) ...@@ -363,6 +367,9 @@ __acquires(&port->port_lock)
struct usb_request *req; struct usb_request *req;
int len; int len;
if (port->write_started >= QUEUE_SIZE)
break;
req = list_entry(pool->next, struct usb_request, list); req = list_entry(pool->next, struct usb_request, list);
len = gs_send_packet(port, req->buf, in->maxpacket); len = gs_send_packet(port, req->buf, in->maxpacket);
if (len == 0) { if (len == 0) {
...@@ -397,6 +404,8 @@ __acquires(&port->port_lock) ...@@ -397,6 +404,8 @@ __acquires(&port->port_lock)
break; break;
} }
port->write_started++;
/* abort immediately after disconnect */ /* abort immediately after disconnect */
if (!port->port_usb) if (!port->port_usb)
break; break;
...@@ -418,7 +427,6 @@ __acquires(&port->port_lock) ...@@ -418,7 +427,6 @@ __acquires(&port->port_lock)
{ {
struct list_head *pool = &port->read_pool; struct list_head *pool = &port->read_pool;
struct usb_ep *out = port->port_usb->out; struct usb_ep *out = port->port_usb->out;
unsigned started = 0;
while (!list_empty(pool)) { while (!list_empty(pool)) {
struct usb_request *req; struct usb_request *req;
...@@ -430,6 +438,9 @@ __acquires(&port->port_lock) ...@@ -430,6 +438,9 @@ __acquires(&port->port_lock)
if (!tty) if (!tty)
break; break;
if (port->read_started >= QUEUE_SIZE)
break;
req = list_entry(pool->next, struct usb_request, list); req = list_entry(pool->next, struct usb_request, list);
list_del(&req->list); list_del(&req->list);
req->length = out->maxpacket; req->length = out->maxpacket;
...@@ -447,13 +458,13 @@ __acquires(&port->port_lock) ...@@ -447,13 +458,13 @@ __acquires(&port->port_lock)
list_add(&req->list, pool); list_add(&req->list, pool);
break; break;
} }
started++; port->read_started++;
/* abort immediately after disconnect */ /* abort immediately after disconnect */
if (!port->port_usb) if (!port->port_usb)
break; break;
} }
return started; return port->read_started;
} }
/* /*
...@@ -535,6 +546,7 @@ static void gs_rx_push(unsigned long _port) ...@@ -535,6 +546,7 @@ static void gs_rx_push(unsigned long _port)
} }
recycle: recycle:
list_move(&req->list, &port->read_pool); list_move(&req->list, &port->read_pool);
port->read_started--;
} }
/* Push from tty to ldisc; without low_latency set this is handled by /* Push from tty to ldisc; without low_latency set this is handled by
...@@ -587,6 +599,7 @@ static void gs_write_complete(struct usb_ep *ep, struct usb_request *req) ...@@ -587,6 +599,7 @@ static void gs_write_complete(struct usb_ep *ep, struct usb_request *req)
spin_lock(&port->port_lock); spin_lock(&port->port_lock);
list_add(&req->list, &port->write_pool); list_add(&req->list, &port->write_pool);
port->write_started--;
switch (req->status) { switch (req->status) {
default: default:
...@@ -608,7 +621,8 @@ static void gs_write_complete(struct usb_ep *ep, struct usb_request *req) ...@@ -608,7 +621,8 @@ static void gs_write_complete(struct usb_ep *ep, struct usb_request *req)
spin_unlock(&port->port_lock); spin_unlock(&port->port_lock);
} }
static void gs_free_requests(struct usb_ep *ep, struct list_head *head) static void gs_free_requests(struct usb_ep *ep, struct list_head *head,
int *allocated)
{ {
struct usb_request *req; struct usb_request *req;
...@@ -616,25 +630,31 @@ static void gs_free_requests(struct usb_ep *ep, struct list_head *head) ...@@ -616,25 +630,31 @@ static void gs_free_requests(struct usb_ep *ep, struct list_head *head)
req = list_entry(head->next, struct usb_request, list); req = list_entry(head->next, struct usb_request, list);
list_del(&req->list); list_del(&req->list);
gs_free_req(ep, req); gs_free_req(ep, req);
if (allocated)
(*allocated)--;
} }
} }
static int gs_alloc_requests(struct usb_ep *ep, struct list_head *head, static int gs_alloc_requests(struct usb_ep *ep, struct list_head *head,
void (*fn)(struct usb_ep *, struct usb_request *)) void (*fn)(struct usb_ep *, struct usb_request *),
int *allocated)
{ {
int i; int i;
struct usb_request *req; struct usb_request *req;
int n = allocated ? QUEUE_SIZE - *allocated : QUEUE_SIZE;
/* Pre-allocate up to QUEUE_SIZE transfers, but if we can't /* Pre-allocate up to QUEUE_SIZE transfers, but if we can't
* do quite that many this time, don't fail ... we just won't * do quite that many this time, don't fail ... we just won't
* be as speedy as we might otherwise be. * be as speedy as we might otherwise be.
*/ */
for (i = 0; i < QUEUE_SIZE; i++) { for (i = 0; i < n; i++) {
req = gs_alloc_req(ep, ep->maxpacket, GFP_ATOMIC); req = gs_alloc_req(ep, ep->maxpacket, GFP_ATOMIC);
if (!req) if (!req)
return list_empty(head) ? -ENOMEM : 0; return list_empty(head) ? -ENOMEM : 0;
req->complete = fn; req->complete = fn;
list_add_tail(&req->list, head); list_add_tail(&req->list, head);
if (allocated)
(*allocated)++;
} }
return 0; return 0;
} }
...@@ -661,14 +681,15 @@ static int gs_start_io(struct gs_port *port) ...@@ -661,14 +681,15 @@ static int gs_start_io(struct gs_port *port)
* configurations may use different endpoints with a given port; * configurations may use different endpoints with a given port;
* and high speed vs full speed changes packet sizes too. * and high speed vs full speed changes packet sizes too.
*/ */
status = gs_alloc_requests(ep, head, gs_read_complete); status = gs_alloc_requests(ep, head, gs_read_complete,
&port->read_allocated);
if (status) if (status)
return status; return status;
status = gs_alloc_requests(port->port_usb->in, &port->write_pool, status = gs_alloc_requests(port->port_usb->in, &port->write_pool,
gs_write_complete); gs_write_complete, &port->write_allocated);
if (status) { if (status) {
gs_free_requests(ep, head); gs_free_requests(ep, head, &port->read_allocated);
return status; return status;
} }
...@@ -680,8 +701,9 @@ static int gs_start_io(struct gs_port *port) ...@@ -680,8 +701,9 @@ static int gs_start_io(struct gs_port *port)
if (started) { if (started) {
tty_wakeup(port->port_tty); tty_wakeup(port->port_tty);
} else { } else {
gs_free_requests(ep, head); gs_free_requests(ep, head, &port->read_allocated);
gs_free_requests(port->port_usb->in, &port->write_pool); gs_free_requests(port->port_usb->in, &port->write_pool,
&port->write_allocated);
status = -EIO; status = -EIO;
} }
...@@ -1315,8 +1337,12 @@ void gserial_disconnect(struct gserial *gser) ...@@ -1315,8 +1337,12 @@ void gserial_disconnect(struct gserial *gser)
spin_lock_irqsave(&port->port_lock, flags); spin_lock_irqsave(&port->port_lock, flags);
if (port->open_count == 0 && !port->openclose) if (port->open_count == 0 && !port->openclose)
gs_buf_free(&port->port_write_buf); gs_buf_free(&port->port_write_buf);
gs_free_requests(gser->out, &port->read_pool); gs_free_requests(gser->out, &port->read_pool, NULL);
gs_free_requests(gser->out, &port->read_queue); gs_free_requests(gser->out, &port->read_queue, NULL);
gs_free_requests(gser->in, &port->write_pool); gs_free_requests(gser->in, &port->write_pool, NULL);
port->read_allocated = port->read_started =
port->write_allocated = port->write_started = 0;
spin_unlock_irqrestore(&port->port_lock, flags); spin_unlock_irqrestore(&port->port_lock, flags);
} }
...@@ -122,7 +122,7 @@ config USB_EHCI_FSL ...@@ -122,7 +122,7 @@ config USB_EHCI_FSL
bool "Support for Freescale on-chip EHCI USB controller" bool "Support for Freescale on-chip EHCI USB controller"
depends on USB_EHCI_HCD && FSL_SOC depends on USB_EHCI_HCD && FSL_SOC
select USB_EHCI_ROOT_HUB_TT select USB_EHCI_ROOT_HUB_TT
select USB_FSL_MPH_DR_OF select USB_FSL_MPH_DR_OF if OF
---help--- ---help---
Variation of ARC USB block used in some Freescale chips. Variation of ARC USB block used in some Freescale chips.
......
...@@ -36,6 +36,8 @@ struct ehci_mxc_priv { ...@@ -36,6 +36,8 @@ struct ehci_mxc_priv {
static int ehci_mxc_setup(struct usb_hcd *hcd) static int ehci_mxc_setup(struct usb_hcd *hcd)
{ {
struct ehci_hcd *ehci = hcd_to_ehci(hcd); struct ehci_hcd *ehci = hcd_to_ehci(hcd);
struct device *dev = hcd->self.controller;
struct mxc_usbh_platform_data *pdata = dev_get_platdata(dev);
int retval; int retval;
/* EHCI registers start at offset 0x100 */ /* EHCI registers start at offset 0x100 */
...@@ -63,6 +65,12 @@ static int ehci_mxc_setup(struct usb_hcd *hcd) ...@@ -63,6 +65,12 @@ static int ehci_mxc_setup(struct usb_hcd *hcd)
ehci_reset(ehci); ehci_reset(ehci);
/* set up the PORTSCx register */
ehci_writel(ehci, pdata->portsc, &ehci->regs->port_status[0]);
/* is this really needed? */
msleep(10);
ehci_port_power(ehci, 0); ehci_port_power(ehci, 0);
return 0; return 0;
} }
...@@ -114,7 +122,7 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) ...@@ -114,7 +122,7 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
struct mxc_usbh_platform_data *pdata = pdev->dev.platform_data; struct mxc_usbh_platform_data *pdata = pdev->dev.platform_data;
struct usb_hcd *hcd; struct usb_hcd *hcd;
struct resource *res; struct resource *res;
int irq, ret, temp; int irq, ret;
struct ehci_mxc_priv *priv; struct ehci_mxc_priv *priv;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
...@@ -188,10 +196,6 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) ...@@ -188,10 +196,6 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
clk_enable(priv->ahbclk); clk_enable(priv->ahbclk);
} }
/* set up the PORTSCx register */
ehci_writel(ehci, pdata->portsc, &ehci->regs->port_status[0]);
mdelay(10);
/* setup specific usb hw */ /* setup specific usb hw */
ret = mxc_initialize_usb_hw(pdev->id, pdata->flags); ret = mxc_initialize_usb_hw(pdev->id, pdata->flags);
if (ret < 0) if (ret < 0)
......
...@@ -273,4 +273,4 @@ static struct platform_driver ohci_hcd_jz4740_driver = { ...@@ -273,4 +273,4 @@ static struct platform_driver ohci_hcd_jz4740_driver = {
}, },
}; };
MODULE_ALIAS("platfrom:jz4740-ohci"); MODULE_ALIAS("platform:jz4740-ohci");
...@@ -553,6 +553,7 @@ static long iowarrior_ioctl(struct file *file, unsigned int cmd, ...@@ -553,6 +553,7 @@ static long iowarrior_ioctl(struct file *file, unsigned int cmd,
/* needed for power consumption */ /* needed for power consumption */
struct usb_config_descriptor *cfg_descriptor = &dev->udev->actconfig->desc; struct usb_config_descriptor *cfg_descriptor = &dev->udev->actconfig->desc;
memset(&info, 0, sizeof(info));
/* directly from the descriptor */ /* directly from the descriptor */
info.vendor = le16_to_cpu(dev->udev->descriptor.idVendor); info.vendor = le16_to_cpu(dev->udev->descriptor.idVendor);
info.product = dev->product_id; info.product = dev->product_id;
......
...@@ -3008,6 +3008,7 @@ sisusb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -3008,6 +3008,7 @@ sisusb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
#else #else
x.sisusb_conactive = 0; x.sisusb_conactive = 0;
#endif #endif
memset(x.sisusb_reserved, 0, sizeof(x.sisusb_reserved));
if (copy_to_user((void __user *)arg, &x, sizeof(x))) if (copy_to_user((void __user *)arg, &x, sizeof(x)))
retval = -EFAULT; retval = -EFAULT;
......
...@@ -171,8 +171,9 @@ static irqreturn_t blackfin_interrupt(int irq, void *__hci) ...@@ -171,8 +171,9 @@ static irqreturn_t blackfin_interrupt(int irq, void *__hci)
} }
/* Start sampling ID pin, when plug is removed from MUSB */ /* Start sampling ID pin, when plug is removed from MUSB */
if (is_otg_enabled(musb) && (musb->xceiv->state == OTG_STATE_B_IDLE if ((is_otg_enabled(musb) && (musb->xceiv->state == OTG_STATE_B_IDLE
|| musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) { || musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) ||
(musb->int_usb & MUSB_INTR_DISCONNECT && is_host_active(musb))) {
mod_timer(&musb_conn_timer, jiffies + TIMER_DELAY); mod_timer(&musb_conn_timer, jiffies + TIMER_DELAY);
musb->a_wait_bcon = TIMER_DELAY; musb->a_wait_bcon = TIMER_DELAY;
} }
...@@ -323,30 +324,8 @@ int musb_platform_set_mode(struct musb *musb, u8 musb_mode) ...@@ -323,30 +324,8 @@ int musb_platform_set_mode(struct musb *musb, u8 musb_mode)
return -EIO; return -EIO;
} }
int __init musb_platform_init(struct musb *musb, void *board_data) static void musb_platform_reg_init(struct musb *musb)
{ {
/*
* Rev 1.0 BF549 EZ-KITs require PE7 to be high for both DEVICE
* and OTG HOST modes, while rev 1.1 and greater require PE7 to
* be low for DEVICE mode and high for HOST mode. We set it high
* here because we are in host mode
*/
if (gpio_request(musb->config->gpio_vrsel, "USB_VRSEL")) {
printk(KERN_ERR "Failed ro request USB_VRSEL GPIO_%d \n",
musb->config->gpio_vrsel);
return -ENODEV;
}
gpio_direction_output(musb->config->gpio_vrsel, 0);
usb_nop_xceiv_register();
musb->xceiv = otg_get_transceiver();
if (!musb->xceiv) {
gpio_free(musb->config->gpio_vrsel);
return -ENODEV;
}
if (ANOMALY_05000346) { if (ANOMALY_05000346) {
bfin_write_USB_APHY_CALIB(ANOMALY_05000346_value); bfin_write_USB_APHY_CALIB(ANOMALY_05000346_value);
SSYNC(); SSYNC();
...@@ -358,7 +337,8 @@ int __init musb_platform_init(struct musb *musb, void *board_data) ...@@ -358,7 +337,8 @@ int __init musb_platform_init(struct musb *musb, void *board_data)
} }
/* Configure PLL oscillator register */ /* Configure PLL oscillator register */
bfin_write_USB_PLLOSC_CTRL(0x30a8); bfin_write_USB_PLLOSC_CTRL(0x3080 |
((480/musb->config->clkin) << 1));
SSYNC(); SSYNC();
bfin_write_USB_SRP_CLKDIV((get_sclk()/1000) / 32 - 1); bfin_write_USB_SRP_CLKDIV((get_sclk()/1000) / 32 - 1);
...@@ -380,6 +360,33 @@ int __init musb_platform_init(struct musb *musb, void *board_data) ...@@ -380,6 +360,33 @@ int __init musb_platform_init(struct musb *musb, void *board_data)
EP2_RX_ENA | EP3_RX_ENA | EP4_RX_ENA | EP2_RX_ENA | EP3_RX_ENA | EP4_RX_ENA |
EP5_RX_ENA | EP6_RX_ENA | EP7_RX_ENA); EP5_RX_ENA | EP6_RX_ENA | EP7_RX_ENA);
SSYNC(); SSYNC();
}
int __init musb_platform_init(struct musb *musb, void *board_data)
{
/*
* Rev 1.0 BF549 EZ-KITs require PE7 to be high for both DEVICE
* and OTG HOST modes, while rev 1.1 and greater require PE7 to
* be low for DEVICE mode and high for HOST mode. We set it high
* here because we are in host mode
*/
if (gpio_request(musb->config->gpio_vrsel, "USB_VRSEL")) {
printk(KERN_ERR "Failed ro request USB_VRSEL GPIO_%d\n",
musb->config->gpio_vrsel);
return -ENODEV;
}
gpio_direction_output(musb->config->gpio_vrsel, 0);
usb_nop_xceiv_register();
musb->xceiv = otg_get_transceiver();
if (!musb->xceiv) {
gpio_free(musb->config->gpio_vrsel);
return -ENODEV;
}
musb_platform_reg_init(musb);
if (is_host_enabled(musb)) { if (is_host_enabled(musb)) {
musb->board_set_vbus = bfin_set_vbus; musb->board_set_vbus = bfin_set_vbus;
...@@ -394,6 +401,27 @@ int __init musb_platform_init(struct musb *musb, void *board_data) ...@@ -394,6 +401,27 @@ int __init musb_platform_init(struct musb *musb, void *board_data)
return 0; return 0;
} }
#ifdef CONFIG_PM
void musb_platform_save_context(struct musb *musb,
struct musb_context_registers *musb_context)
{
if (is_host_active(musb))
/*
* During hibernate gpio_vrsel will change from high to low
* low which will generate wakeup event resume the system
* immediately. Set it to 0 before hibernate to avoid this
* wakeup event.
*/
gpio_set_value(musb->config->gpio_vrsel, 0);
}
void musb_platform_restore_context(struct musb *musb,
struct musb_context_registers *musb_context)
{
musb_platform_reg_init(musb);
}
#endif
int musb_platform_exit(struct musb *musb) int musb_platform_exit(struct musb *musb)
{ {
gpio_free(musb->config->gpio_vrsel); gpio_free(musb->config->gpio_vrsel);
......
...@@ -552,7 +552,8 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, ...@@ -552,7 +552,8 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
if (int_usb & MUSB_INTR_SESSREQ) { if (int_usb & MUSB_INTR_SESSREQ) {
void __iomem *mbase = musb->mregs; void __iomem *mbase = musb->mregs;
if (devctl & MUSB_DEVCTL_BDEVICE) { if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS
&& (devctl & MUSB_DEVCTL_BDEVICE)) {
DBG(3, "SessReq while on B state\n"); DBG(3, "SessReq while on B state\n");
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -1052,6 +1053,11 @@ static void musb_shutdown(struct platform_device *pdev) ...@@ -1052,6 +1053,11 @@ static void musb_shutdown(struct platform_device *pdev)
clk_put(musb->clock); clk_put(musb->clock);
spin_unlock_irqrestore(&musb->lock, flags); spin_unlock_irqrestore(&musb->lock, flags);
if (!is_otg_enabled(musb) && is_host_enabled(musb))
usb_remove_hcd(musb_to_hcd(musb));
musb_writeb(musb->mregs, MUSB_DEVCTL, 0);
musb_platform_exit(musb);
/* FIXME power down */ /* FIXME power down */
} }
...@@ -2244,13 +2250,6 @@ static int __exit musb_remove(struct platform_device *pdev) ...@@ -2244,13 +2250,6 @@ static int __exit musb_remove(struct platform_device *pdev)
*/ */
musb_exit_debugfs(musb); musb_exit_debugfs(musb);
musb_shutdown(pdev); musb_shutdown(pdev);
#ifdef CONFIG_USB_MUSB_HDRC_HCD
if (musb->board_mode == MUSB_HOST)
usb_remove_hcd(musb_to_hcd(musb));
#endif
musb_writeb(musb->mregs, MUSB_DEVCTL, 0);
musb_platform_exit(musb);
musb_writeb(musb->mregs, MUSB_DEVCTL, 0);
musb_free(musb); musb_free(musb);
iounmap(ctrl_base); iounmap(ctrl_base);
...@@ -2411,9 +2410,6 @@ static int musb_suspend(struct device *dev) ...@@ -2411,9 +2410,6 @@ static int musb_suspend(struct device *dev)
unsigned long flags; unsigned long flags;
struct musb *musb = dev_to_musb(&pdev->dev); struct musb *musb = dev_to_musb(&pdev->dev);
if (!musb->clock)
return 0;
spin_lock_irqsave(&musb->lock, flags); spin_lock_irqsave(&musb->lock, flags);
if (is_peripheral_active(musb)) { if (is_peripheral_active(musb)) {
...@@ -2428,10 +2424,12 @@ static int musb_suspend(struct device *dev) ...@@ -2428,10 +2424,12 @@ static int musb_suspend(struct device *dev)
musb_save_context(musb); musb_save_context(musb);
if (musb->set_clock) if (musb->clock) {
musb->set_clock(musb->clock, 0); if (musb->set_clock)
else musb->set_clock(musb->clock, 0);
clk_disable(musb->clock); else
clk_disable(musb->clock);
}
spin_unlock_irqrestore(&musb->lock, flags); spin_unlock_irqrestore(&musb->lock, flags);
return 0; return 0;
} }
...@@ -2441,13 +2439,12 @@ static int musb_resume_noirq(struct device *dev) ...@@ -2441,13 +2439,12 @@ static int musb_resume_noirq(struct device *dev)
struct platform_device *pdev = to_platform_device(dev); struct platform_device *pdev = to_platform_device(dev);
struct musb *musb = dev_to_musb(&pdev->dev); struct musb *musb = dev_to_musb(&pdev->dev);
if (!musb->clock) if (musb->clock) {
return 0; if (musb->set_clock)
musb->set_clock(musb->clock, 1);
if (musb->set_clock) else
musb->set_clock(musb->clock, 1); clk_enable(musb->clock);
else }
clk_enable(musb->clock);
musb_restore_context(musb); musb_restore_context(musb);
......
...@@ -487,7 +487,7 @@ struct musb_context_registers { ...@@ -487,7 +487,7 @@ struct musb_context_registers {
}; };
#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) || \ #if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) || \
defined(CONFIG_ARCH_OMAP4) defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_BLACKFIN)
extern void musb_platform_save_context(struct musb *musb, extern void musb_platform_save_context(struct musb *musb,
struct musb_context_registers *musb_context); struct musb_context_registers *musb_context);
extern void musb_platform_restore_context(struct musb *musb, extern void musb_platform_restore_context(struct musb *musb,
......
...@@ -644,10 +644,8 @@ static void rxstate(struct musb *musb, struct musb_request *req) ...@@ -644,10 +644,8 @@ static void rxstate(struct musb *musb, struct musb_request *req)
*/ */
csr |= MUSB_RXCSR_DMAENAB; csr |= MUSB_RXCSR_DMAENAB;
if (!musb_ep->hb_mult &&
musb_ep->hw_ep->rx_double_buffered)
csr |= MUSB_RXCSR_AUTOCLEAR;
#ifdef USE_MODE1 #ifdef USE_MODE1
csr |= MUSB_RXCSR_AUTOCLEAR;
/* csr |= MUSB_RXCSR_DMAMODE; */ /* csr |= MUSB_RXCSR_DMAMODE; */
/* this special sequence (enabling and then /* this special sequence (enabling and then
...@@ -656,6 +654,10 @@ static void rxstate(struct musb *musb, struct musb_request *req) ...@@ -656,6 +654,10 @@ static void rxstate(struct musb *musb, struct musb_request *req)
*/ */
musb_writew(epio, MUSB_RXCSR, musb_writew(epio, MUSB_RXCSR,
csr | MUSB_RXCSR_DMAMODE); csr | MUSB_RXCSR_DMAMODE);
#else
if (!musb_ep->hb_mult &&
musb_ep->hw_ep->rx_double_buffered)
csr |= MUSB_RXCSR_AUTOCLEAR;
#endif #endif
musb_writew(epio, MUSB_RXCSR, csr); musb_writew(epio, MUSB_RXCSR, csr);
...@@ -807,7 +809,7 @@ void musb_g_rx(struct musb *musb, u8 epnum) ...@@ -807,7 +809,7 @@ void musb_g_rx(struct musb *musb, u8 epnum)
#if defined(CONFIG_USB_INVENTRA_DMA) || defined(CONFIG_USB_TUSB_OMAP_DMA) #if defined(CONFIG_USB_INVENTRA_DMA) || defined(CONFIG_USB_TUSB_OMAP_DMA)
/* Autoclear doesn't clear RxPktRdy for short packets */ /* Autoclear doesn't clear RxPktRdy for short packets */
if ((dma->desired_mode == 0) if ((dma->desired_mode == 0 && !hw_ep->rx_double_buffered)
|| (dma->actual_len || (dma->actual_len
& (musb_ep->packet_sz - 1))) { & (musb_ep->packet_sz - 1))) {
/* ack the read! */ /* ack the read! */
...@@ -818,8 +820,16 @@ void musb_g_rx(struct musb *musb, u8 epnum) ...@@ -818,8 +820,16 @@ void musb_g_rx(struct musb *musb, u8 epnum)
/* incomplete, and not short? wait for next IN packet */ /* incomplete, and not short? wait for next IN packet */
if ((request->actual < request->length) if ((request->actual < request->length)
&& (musb_ep->dma->actual_len && (musb_ep->dma->actual_len
== musb_ep->packet_sz)) == musb_ep->packet_sz)) {
/* In double buffer case, continue to unload fifo if
* there is Rx packet in FIFO.
**/
csr = musb_readw(epio, MUSB_RXCSR);
if ((csr & MUSB_RXCSR_RXPKTRDY) &&
hw_ep->rx_double_buffered)
goto exit;
return; return;
}
#endif #endif
musb_g_giveback(musb_ep, request, 0); musb_g_giveback(musb_ep, request, 0);
...@@ -827,7 +837,7 @@ void musb_g_rx(struct musb *musb, u8 epnum) ...@@ -827,7 +837,7 @@ void musb_g_rx(struct musb *musb, u8 epnum)
if (!request) if (!request)
return; return;
} }
exit:
/* Analyze request */ /* Analyze request */
rxstate(musb, to_musb_request(request)); rxstate(musb, to_musb_request(request));
} }
...@@ -916,13 +926,9 @@ static int musb_gadget_enable(struct usb_ep *ep, ...@@ -916,13 +926,9 @@ static int musb_gadget_enable(struct usb_ep *ep,
* likewise high bandwidth periodic tx * likewise high bandwidth periodic tx
*/ */
/* Set TXMAXP with the FIFO size of the endpoint /* Set TXMAXP with the FIFO size of the endpoint
* to disable double buffering mode. Currently, It seems that double * to disable double buffering mode.
* buffering has problem if musb RTL revision number < 2.0.
*/ */
if (musb->hwvers < MUSB_HWVERS_2000) musb_writew(regs, MUSB_TXMAXP, musb_ep->packet_sz | (musb_ep->hb_mult << 11));
musb_writew(regs, MUSB_TXMAXP, hw_ep->max_packet_sz_tx);
else
musb_writew(regs, MUSB_TXMAXP, musb_ep->packet_sz | (musb_ep->hb_mult << 11));
csr = MUSB_TXCSR_MODE | MUSB_TXCSR_CLRDATATOG; csr = MUSB_TXCSR_MODE | MUSB_TXCSR_CLRDATATOG;
if (musb_readw(regs, MUSB_TXCSR) if (musb_readw(regs, MUSB_TXCSR)
...@@ -958,10 +964,7 @@ static int musb_gadget_enable(struct usb_ep *ep, ...@@ -958,10 +964,7 @@ static int musb_gadget_enable(struct usb_ep *ep,
/* Set RXMAXP with the FIFO size of the endpoint /* Set RXMAXP with the FIFO size of the endpoint
* to disable double buffering mode. * to disable double buffering mode.
*/ */
if (musb->hwvers < MUSB_HWVERS_2000) musb_writew(regs, MUSB_RXMAXP, musb_ep->packet_sz | (musb_ep->hb_mult << 11));
musb_writew(regs, MUSB_RXMAXP, hw_ep->max_packet_sz_rx);
else
musb_writew(regs, MUSB_RXMAXP, musb_ep->packet_sz | (musb_ep->hb_mult << 11));
/* force shared fifo to OUT-only mode */ /* force shared fifo to OUT-only mode */
if (hw_ep->is_shared_fifo) { if (hw_ep->is_shared_fifo) {
...@@ -1166,8 +1169,6 @@ static int musb_gadget_queue(struct usb_ep *ep, struct usb_request *req, ...@@ -1166,8 +1169,6 @@ static int musb_gadget_queue(struct usb_ep *ep, struct usb_request *req,
: DMA_FROM_DEVICE); : DMA_FROM_DEVICE);
request->mapped = 0; request->mapped = 0;
} }
} else if (!req->buf) {
return -ENODATA;
} else } else
request->mapped = 0; request->mapped = 0;
...@@ -1695,8 +1696,10 @@ int __init musb_gadget_setup(struct musb *musb) ...@@ -1695,8 +1696,10 @@ int __init musb_gadget_setup(struct musb *musb)
musb_platform_try_idle(musb, 0); musb_platform_try_idle(musb, 0);
status = device_register(&musb->g.dev); status = device_register(&musb->g.dev);
if (status != 0) if (status != 0) {
put_device(&musb->g.dev);
the_gadget = NULL; the_gadget = NULL;
}
return status; return status;
} }
......
...@@ -633,8 +633,9 @@ static inline u8 musb_read_txhubaddr(void __iomem *mbase, u8 epnum) ...@@ -633,8 +633,9 @@ static inline u8 musb_read_txhubaddr(void __iomem *mbase, u8 epnum)
return 0; return 0;
} }
static inline void musb_read_txhubport(void __iomem *mbase, u8 epnum) static inline u8 musb_read_txhubport(void __iomem *mbase, u8 epnum)
{ {
return 0;
} }
#endif /* CONFIG_BLACKFIN */ #endif /* CONFIG_BLACKFIN */
......
...@@ -158,6 +158,8 @@ static int dma_channel_program(struct dma_channel *channel, ...@@ -158,6 +158,8 @@ static int dma_channel_program(struct dma_channel *channel,
dma_addr_t dma_addr, u32 len) dma_addr_t dma_addr, u32 len)
{ {
struct musb_dma_channel *musb_channel = channel->private_data; struct musb_dma_channel *musb_channel = channel->private_data;
struct musb_dma_controller *controller = musb_channel->controller;
struct musb *musb = controller->private_data;
DBG(2, "ep%d-%s pkt_sz %d, dma_addr 0x%x length %d, mode %d\n", DBG(2, "ep%d-%s pkt_sz %d, dma_addr 0x%x length %d, mode %d\n",
musb_channel->epnum, musb_channel->epnum,
...@@ -167,6 +169,18 @@ static int dma_channel_program(struct dma_channel *channel, ...@@ -167,6 +169,18 @@ static int dma_channel_program(struct dma_channel *channel,
BUG_ON(channel->status == MUSB_DMA_STATUS_UNKNOWN || BUG_ON(channel->status == MUSB_DMA_STATUS_UNKNOWN ||
channel->status == MUSB_DMA_STATUS_BUSY); channel->status == MUSB_DMA_STATUS_BUSY);
/*
* The DMA engine in RTL1.8 and above cannot handle
* DMA addresses that are not aligned to a 4 byte boundary.
* It ends up masking the last two bits of the address
* programmed in DMA_ADDR.
*
* Fail such DMA transfers, so that the backup PIO mode
* can carry out the transfer
*/
if ((musb->hwvers >= MUSB_HWVERS_1800) && (dma_addr % 4))
return false;
channel->actual_len = 0; channel->actual_len = 0;
musb_channel->start_addr = dma_addr; musb_channel->start_addr = dma_addr;
musb_channel->len = len; musb_channel->len = len;
......
...@@ -794,6 +794,8 @@ static struct usb_device_id id_table_combined [] = { ...@@ -794,6 +794,8 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LOGBOOKML_PID) }, { USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LOGBOOKML_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LS_LOGBOOK_PID) }, { USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LS_LOGBOOK_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_HS_LOGBOOK_PID) }, { USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_HS_LOGBOOK_PID) },
{ USB_DEVICE(QIHARDWARE_VID, MILKYMISTONE_JTAGSERIAL_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ }, /* Optional parameter entry */ { }, /* Optional parameter entry */
{ } /* Terminating entry */ { } /* Terminating entry */
}; };
......
...@@ -1100,3 +1100,10 @@ ...@@ -1100,3 +1100,10 @@
#define FTDI_SCIENCESCOPE_LOGBOOKML_PID 0xFF18 #define FTDI_SCIENCESCOPE_LOGBOOKML_PID 0xFF18
#define FTDI_SCIENCESCOPE_LS_LOGBOOK_PID 0xFF1C #define FTDI_SCIENCESCOPE_LS_LOGBOOK_PID 0xFF1C
#define FTDI_SCIENCESCOPE_HS_LOGBOOK_PID 0xFF1D #define FTDI_SCIENCESCOPE_HS_LOGBOOK_PID 0xFF1D
/*
* Milkymist One JTAG/Serial
*/
#define QIHARDWARE_VID 0x20B7
#define MILKYMISTONE_JTAGSERIAL_PID 0x0713
...@@ -518,7 +518,7 @@ static const struct usb_device_id option_ids[] = { ...@@ -518,7 +518,7 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4505, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4505, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3765, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3765, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ETS1220, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ETS1220, 0xff, 0xff, 0xff) },
{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E14AC) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E14AC, 0xff, 0xff, 0xff) },
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) },
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) },
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V740) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V740) },
......
...@@ -326,7 +326,8 @@ int uwb_rsv_find_best_allocation(struct uwb_rsv *rsv, struct uwb_mas_bm *availab ...@@ -326,7 +326,8 @@ int uwb_rsv_find_best_allocation(struct uwb_rsv *rsv, struct uwb_mas_bm *availab
int bit_index; int bit_index;
ai = kzalloc(sizeof(struct uwb_rsv_alloc_info), GFP_KERNEL); ai = kzalloc(sizeof(struct uwb_rsv_alloc_info), GFP_KERNEL);
if (!ai)
return UWB_RSV_ALLOC_NOT_FOUND;
ai->min_mas = rsv->min_mas; ai->min_mas = rsv->min_mas;
ai->max_mas = rsv->max_mas; ai->max_mas = rsv->max_mas;
ai->max_interval = rsv->max_interval; ai->max_interval = rsv->max_interval;
......
...@@ -797,7 +797,7 @@ struct usbdrv_wrap { ...@@ -797,7 +797,7 @@ struct usbdrv_wrap {
* @disconnect: Called when the interface is no longer accessible, usually * @disconnect: Called when the interface is no longer accessible, usually
* because its device has been (or is being) disconnected or the * because its device has been (or is being) disconnected or the
* driver module is being unloaded. * driver module is being unloaded.
* @ioctl: Used for drivers that want to talk to userspace through * @unlocked_ioctl: Used for drivers that want to talk to userspace through
* the "usbfs" filesystem. This lets devices provide ways to * the "usbfs" filesystem. This lets devices provide ways to
* expose information to user space regardless of where they * expose information to user space regardless of where they
* do (or don't) show up otherwise in the filesystem. * do (or don't) show up otherwise in the filesystem.
......
...@@ -89,6 +89,8 @@ struct musb_hdrc_config { ...@@ -89,6 +89,8 @@ struct musb_hdrc_config {
/* A GPIO controlling VRSEL in Blackfin */ /* A GPIO controlling VRSEL in Blackfin */
unsigned int gpio_vrsel; unsigned int gpio_vrsel;
unsigned int gpio_vrsel_active; unsigned int gpio_vrsel_active;
/* musb CLKIN in Blackfin in MHZ */
unsigned char clkin;
#endif #endif
}; };
......
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