Commit c6c59927 authored by Linus Torvalds's avatar Linus Torvalds

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: (32 commits)
  USB: serial: no unnecessary GFP_ATOMIC in oti6858
  USB: serial: fix race between unthrottle and completion handler in visor
  USB: serial: fix assumption that throttle/unthrottle cannot sleep
  USB: serial: fix race between unthrottle and completion handler in symbolserial
  USB: serial: fix race between unthrottle and completion handler in opticon
  USB: ehci: Fix isoc scheduling boundary checking.
  USB: storage: When a device returns no sense data, call it a Hardware Error
  USB: small fix in error case of suspend in generic usbserial code
  USB: visor: fix trivial accounting bug in visor driver
  USB: Fix throttling in generic usbserial driver
  USB: cp210x: Add support for the DW700 UART
  USB: ipaq: fix oops when device is plugged in
  USB: isp1362: fix build warnings on 64-bit systems
  USB: gadget: imx_udc: Use resource size
  USB: storage: iRiver P7 UNUSUAL_DEV patch
  USB: musb: make HAVE_CLK support optional
  USB: xhci: Fix dropping endpoints from the xHC schedule.
  USB: xhci: Don't wait for a disable slot cmd when HC dies.
  USB: xhci: Handle canceled URBs when HC dies.
  USB: xhci: Stop debugging polling loop when HC dies.
  ...
parents ff945afb 40d28582
...@@ -39,7 +39,7 @@ ...@@ -39,7 +39,7 @@
#define USBTMC_SIZE_IOBUFFER 2048 #define USBTMC_SIZE_IOBUFFER 2048
/* Default USB timeout (in milliseconds) */ /* Default USB timeout (in milliseconds) */
#define USBTMC_TIMEOUT 10 #define USBTMC_TIMEOUT 5000
/* /*
* Maximum number of read cycles to empty bulk in endpoint during CLEAR and * Maximum number of read cycles to empty bulk in endpoint during CLEAR and
......
...@@ -1402,7 +1402,8 @@ static int __init imx_udc_probe(struct platform_device *pdev) ...@@ -1402,7 +1402,8 @@ static int __init imx_udc_probe(struct platform_device *pdev)
struct clk *clk; struct clk *clk;
void __iomem *base; void __iomem *base;
int ret = 0; int ret = 0;
int i, res_size; int i;
resource_size_t res_size;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) { if (!res) {
...@@ -1416,7 +1417,7 @@ static int __init imx_udc_probe(struct platform_device *pdev) ...@@ -1416,7 +1417,7 @@ static int __init imx_udc_probe(struct platform_device *pdev)
return -ENODEV; return -ENODEV;
} }
res_size = res->end - res->start + 1; res_size = resource_size(res);
if (!request_mem_region(res->start, res_size, res->name)) { if (!request_mem_region(res->start, res_size, res->name)) {
dev_err(&pdev->dev, "can't allocate %d bytes at %d address\n", dev_err(&pdev->dev, "can't allocate %d bytes at %d address\n",
res_size, res->start); res_size, res->start);
...@@ -1527,8 +1528,7 @@ static int __exit imx_udc_remove(struct platform_device *pdev) ...@@ -1527,8 +1528,7 @@ static int __exit imx_udc_remove(struct platform_device *pdev)
clk_disable(imx_usb->clk); clk_disable(imx_usb->clk);
iounmap(imx_usb->base); iounmap(imx_usb->base);
release_mem_region(imx_usb->res->start, release_mem_region(imx_usb->res->start, resource_size(imx_usb->res));
imx_usb->res->end - imx_usb->res->start + 1);
if (pdata->exit) if (pdata->exit)
pdata->exit(&pdev->dev); pdata->exit(&pdev->dev);
......
...@@ -1425,6 +1425,7 @@ iso_stream_schedule ( ...@@ -1425,6 +1425,7 @@ iso_stream_schedule (
status = -EFBIG; status = -EFBIG;
goto fail; goto fail;
} }
stream->next_uframe = start;
goto ready; goto ready;
} }
......
...@@ -2284,10 +2284,10 @@ static int isp1362_mem_config(struct usb_hcd *hcd) ...@@ -2284,10 +2284,10 @@ static int isp1362_mem_config(struct usb_hcd *hcd)
dev_info(hcd->self.controller, "ISP1362 Memory usage:\n"); dev_info(hcd->self.controller, "ISP1362 Memory usage:\n");
dev_info(hcd->self.controller, " ISTL: 2 * %4d: %4d @ $%04x:$%04x\n", dev_info(hcd->self.controller, " ISTL: 2 * %4d: %4d @ $%04x:$%04x\n",
istl_size / 2, istl_size, 0, istl_size / 2); istl_size / 2, istl_size, 0, istl_size / 2);
dev_info(hcd->self.controller, " INTL: %4d * (%3u+8): %4d @ $%04x\n", dev_info(hcd->self.controller, " INTL: %4d * (%3lu+8): %4d @ $%04x\n",
ISP1362_INTL_BUFFERS, intl_blksize - PTD_HEADER_SIZE, ISP1362_INTL_BUFFERS, intl_blksize - PTD_HEADER_SIZE,
intl_size, istl_size); intl_size, istl_size);
dev_info(hcd->self.controller, " ATL : %4d * (%3u+8): %4d @ $%04x\n", dev_info(hcd->self.controller, " ATL : %4d * (%3lu+8): %4d @ $%04x\n",
atl_buffers, atl_blksize - PTD_HEADER_SIZE, atl_buffers, atl_blksize - PTD_HEADER_SIZE,
atl_size, istl_size + intl_size); atl_size, istl_size + intl_size);
dev_info(hcd->self.controller, " USED/FREE: %4d %4d\n", total, dev_info(hcd->self.controller, " USED/FREE: %4d %4d\n", total,
...@@ -2677,12 +2677,12 @@ static int __devexit isp1362_remove(struct platform_device *pdev) ...@@ -2677,12 +2677,12 @@ static int __devexit isp1362_remove(struct platform_device *pdev)
DBG(0, "%s: Removing HCD\n", __func__); DBG(0, "%s: Removing HCD\n", __func__);
usb_remove_hcd(hcd); usb_remove_hcd(hcd);
DBG(0, "%s: Unmapping data_reg @ %08x\n", __func__, DBG(0, "%s: Unmapping data_reg @ %p\n", __func__,
(u32)isp1362_hcd->data_reg); isp1362_hcd->data_reg);
iounmap(isp1362_hcd->data_reg); iounmap(isp1362_hcd->data_reg);
DBG(0, "%s: Unmapping addr_reg @ %08x\n", __func__, DBG(0, "%s: Unmapping addr_reg @ %p\n", __func__,
(u32)isp1362_hcd->addr_reg); isp1362_hcd->addr_reg);
iounmap(isp1362_hcd->addr_reg); iounmap(isp1362_hcd->addr_reg);
res = platform_get_resource(pdev, IORESOURCE_MEM, 1); res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
...@@ -2810,16 +2810,16 @@ static int __init isp1362_probe(struct platform_device *pdev) ...@@ -2810,16 +2810,16 @@ static int __init isp1362_probe(struct platform_device *pdev)
return 0; return 0;
err6: err6:
DBG(0, "%s: Freeing dev %08x\n", __func__, (u32)isp1362_hcd); DBG(0, "%s: Freeing dev %p\n", __func__, isp1362_hcd);
usb_put_hcd(hcd); usb_put_hcd(hcd);
err5: err5:
DBG(0, "%s: Unmapping data_reg @ %08x\n", __func__, (u32)data_reg); DBG(0, "%s: Unmapping data_reg @ %p\n", __func__, data_reg);
iounmap(data_reg); iounmap(data_reg);
err4: err4:
DBG(0, "%s: Releasing mem region %08lx\n", __func__, (long unsigned int)data->start); DBG(0, "%s: Releasing mem region %08lx\n", __func__, (long unsigned int)data->start);
release_mem_region(data->start, resource_len(data)); release_mem_region(data->start, resource_len(data));
err3: err3:
DBG(0, "%s: Unmapping addr_reg @ %08x\n", __func__, (u32)addr_reg); DBG(0, "%s: Unmapping addr_reg @ %p\n", __func__, addr_reg);
iounmap(addr_reg); iounmap(addr_reg);
err2: err2:
DBG(0, "%s: Releasing mem region %08lx\n", __func__, (long unsigned int)addr->start); DBG(0, "%s: Releasing mem region %08lx\n", __func__, (long unsigned int)addr->start);
......
...@@ -580,7 +580,7 @@ static inline const char *ISP1362_INT_NAME(int n) ...@@ -580,7 +580,7 @@ static inline const char *ISP1362_INT_NAME(int n)
static inline void ALIGNSTAT(struct isp1362_hcd *isp1362_hcd, void *ptr) static inline void ALIGNSTAT(struct isp1362_hcd *isp1362_hcd, void *ptr)
{ {
unsigned p = (unsigned)ptr; unsigned long p = (unsigned long)ptr;
if (!(p & 0xf)) if (!(p & 0xf))
isp1362_hcd->stat16++; isp1362_hcd->stat16++;
else if (!(p & 0x7)) else if (!(p & 0x7))
...@@ -770,7 +770,7 @@ static void isp1362_write_fifo(struct isp1362_hcd *isp1362_hcd, void *buf, u16 l ...@@ -770,7 +770,7 @@ static void isp1362_write_fifo(struct isp1362_hcd *isp1362_hcd, void *buf, u16 l
if (!len) if (!len)
return; return;
if ((unsigned)dp & 0x1) { if ((unsigned long)dp & 0x1) {
/* not aligned */ /* not aligned */
for (; len > 1; len -= 2) { for (; len > 1; len -= 2) {
data = *dp++; data = *dp++;
...@@ -962,8 +962,8 @@ static void isp1362_read_buffer(struct isp1362_hcd *isp1362_hcd, void *buf, u16 ...@@ -962,8 +962,8 @@ static void isp1362_read_buffer(struct isp1362_hcd *isp1362_hcd, void *buf, u16
isp1362_write_diraddr(isp1362_hcd, offset, len); isp1362_write_diraddr(isp1362_hcd, offset, len);
DBG(3, "%s: Reading %d byte from buffer @%04x to memory @ %08x\n", __func__, DBG(3, "%s: Reading %d byte from buffer @%04x to memory @ %p\n",
len, offset, (u32)buf); __func__, len, offset, buf);
isp1362_write_reg16(isp1362_hcd, HCuPINT, HCuPINT_EOT); isp1362_write_reg16(isp1362_hcd, HCuPINT, HCuPINT_EOT);
_WARN_ON((isp1362_read_reg16(isp1362_hcd, HCuPINT) & HCuPINT_EOT)); _WARN_ON((isp1362_read_reg16(isp1362_hcd, HCuPINT) & HCuPINT_EOT));
...@@ -982,8 +982,8 @@ static void isp1362_write_buffer(struct isp1362_hcd *isp1362_hcd, void *buf, u16 ...@@ -982,8 +982,8 @@ static void isp1362_write_buffer(struct isp1362_hcd *isp1362_hcd, void *buf, u16
isp1362_write_diraddr(isp1362_hcd, offset, len); isp1362_write_diraddr(isp1362_hcd, offset, len);
DBG(3, "%s: Writing %d byte to buffer @%04x from memory @ %08x\n", __func__, DBG(3, "%s: Writing %d byte to buffer @%04x from memory @ %p\n",
len, offset, (u32)buf); __func__, len, offset, buf);
isp1362_write_reg16(isp1362_hcd, HCuPINT, HCuPINT_EOT); isp1362_write_reg16(isp1362_hcd, HCuPINT, HCuPINT_EOT);
_WARN_ON((isp1362_read_reg16(isp1362_hcd, HCuPINT) & HCuPINT_EOT)); _WARN_ON((isp1362_read_reg16(isp1362_hcd, HCuPINT) & HCuPINT_EOT));
......
...@@ -335,6 +335,12 @@ void xhci_event_ring_work(unsigned long arg) ...@@ -335,6 +335,12 @@ void xhci_event_ring_work(unsigned long arg)
spin_lock_irqsave(&xhci->lock, flags); spin_lock_irqsave(&xhci->lock, flags);
temp = xhci_readl(xhci, &xhci->op_regs->status); temp = xhci_readl(xhci, &xhci->op_regs->status);
xhci_dbg(xhci, "op reg status = 0x%x\n", temp); xhci_dbg(xhci, "op reg status = 0x%x\n", temp);
if (temp == 0xffffffff) {
xhci_dbg(xhci, "HW died, polling stopped.\n");
spin_unlock_irqrestore(&xhci->lock, flags);
return;
}
temp = xhci_readl(xhci, &xhci->ir_set->irq_pending); temp = xhci_readl(xhci, &xhci->ir_set->irq_pending);
xhci_dbg(xhci, "ir_set 0 pending = 0x%x\n", temp); xhci_dbg(xhci, "ir_set 0 pending = 0x%x\n", temp);
xhci_dbg(xhci, "No-op commands handled = %d\n", xhci->noops_handled); xhci_dbg(xhci, "No-op commands handled = %d\n", xhci->noops_handled);
...@@ -776,6 +782,7 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) ...@@ -776,6 +782,7 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
{ {
unsigned long flags; unsigned long flags;
int ret; int ret;
u32 temp;
struct xhci_hcd *xhci; struct xhci_hcd *xhci;
struct xhci_td *td; struct xhci_td *td;
unsigned int ep_index; unsigned int ep_index;
...@@ -788,6 +795,17 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) ...@@ -788,6 +795,17 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
ret = usb_hcd_check_unlink_urb(hcd, urb, status); ret = usb_hcd_check_unlink_urb(hcd, urb, status);
if (ret || !urb->hcpriv) if (ret || !urb->hcpriv)
goto done; goto done;
temp = xhci_readl(xhci, &xhci->op_regs->status);
if (temp == 0xffffffff) {
xhci_dbg(xhci, "HW died, freeing TD.\n");
td = (struct xhci_td *) urb->hcpriv;
usb_hcd_unlink_urb_from_ep(hcd, urb);
spin_unlock_irqrestore(&xhci->lock, flags);
usb_hcd_giveback_urb(xhci_to_hcd(xhci), urb, -ESHUTDOWN);
kfree(td);
return ret;
}
xhci_dbg(xhci, "Cancel URB %p\n", urb); xhci_dbg(xhci, "Cancel URB %p\n", urb);
xhci_dbg(xhci, "Event ring:\n"); xhci_dbg(xhci, "Event ring:\n");
...@@ -877,7 +895,7 @@ int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev, ...@@ -877,7 +895,7 @@ int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
ctrl_ctx->drop_flags |= drop_flag; ctrl_ctx->drop_flags |= drop_flag;
new_drop_flags = ctrl_ctx->drop_flags; new_drop_flags = ctrl_ctx->drop_flags;
ctrl_ctx->add_flags = ~drop_flag; ctrl_ctx->add_flags &= ~drop_flag;
new_add_flags = ctrl_ctx->add_flags; new_add_flags = ctrl_ctx->add_flags;
last_ctx = xhci_last_valid_endpoint(ctrl_ctx->add_flags); last_ctx = xhci_last_valid_endpoint(ctrl_ctx->add_flags);
...@@ -1410,11 +1428,20 @@ void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev) ...@@ -1410,11 +1428,20 @@ void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev)
{ {
struct xhci_hcd *xhci = hcd_to_xhci(hcd); struct xhci_hcd *xhci = hcd_to_xhci(hcd);
unsigned long flags; unsigned long flags;
u32 state;
if (udev->slot_id == 0) if (udev->slot_id == 0)
return; return;
spin_lock_irqsave(&xhci->lock, flags); spin_lock_irqsave(&xhci->lock, flags);
/* Don't disable the slot if the host controller is dead. */
state = xhci_readl(xhci, &xhci->op_regs->status);
if (state == 0xffffffff) {
xhci_free_virt_device(xhci, udev->slot_id);
spin_unlock_irqrestore(&xhci->lock, flags);
return;
}
if (xhci_queue_slot_control(xhci, TRB_DISABLE_SLOT, udev->slot_id)) { if (xhci_queue_slot_control(xhci, TRB_DISABLE_SLOT, udev->slot_id)) {
spin_unlock_irqrestore(&xhci->lock, flags); spin_unlock_irqrestore(&xhci->lock, flags);
xhci_dbg(xhci, "FIXME: allocate a command ring segment\n"); xhci_dbg(xhci, "FIXME: allocate a command ring segment\n");
......
...@@ -313,7 +313,8 @@ static int lcd_probe(struct usb_interface *interface, const struct usb_device_id ...@@ -313,7 +313,8 @@ static int lcd_probe(struct usb_interface *interface, const struct usb_device_id
if (le16_to_cpu(dev->udev->descriptor.idProduct) != 0x0001) { if (le16_to_cpu(dev->udev->descriptor.idProduct) != 0x0001) {
dev_warn(&interface->dev, "USBLCD model not supported.\n"); dev_warn(&interface->dev, "USBLCD model not supported.\n");
return -ENODEV; retval = -ENODEV;
goto error;
} }
/* set up the endpoint information */ /* set up the endpoint information */
......
...@@ -8,7 +8,7 @@ comment "Enable Host or Gadget support to see Inventra options" ...@@ -8,7 +8,7 @@ comment "Enable Host or Gadget support to see Inventra options"
# (M)HDRC = (Multipoint) Highspeed Dual-Role Controller # (M)HDRC = (Multipoint) Highspeed Dual-Role Controller
config USB_MUSB_HDRC config USB_MUSB_HDRC
depends on (USB || USB_GADGET) && HAVE_CLK depends on (USB || USB_GADGET)
depends on !SUPERH depends on !SUPERH
select NOP_USB_XCEIV if ARCH_DAVINCI select NOP_USB_XCEIV if ARCH_DAVINCI
select TWL4030_USB if MACH_OMAP_3430SDP select TWL4030_USB if MACH_OMAP_3430SDP
......
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/clk.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/io.h> #include <linux/io.h>
......
...@@ -95,6 +95,13 @@ struct musb_ep; ...@@ -95,6 +95,13 @@ struct musb_ep;
#endif #endif
#endif /* need MUSB gadget selection */ #endif /* need MUSB gadget selection */
#ifndef CONFIG_HAVE_CLK
/* Dummy stub for clk framework */
#define clk_get(dev, id) NULL
#define clk_put(clock) do {} while (0)
#define clk_enable(clock) do {} while (0)
#define clk_disable(clock) do {} while (0)
#endif
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
#include <linux/fs.h> #include <linux/fs.h>
......
...@@ -439,15 +439,6 @@ static inline void musb_write_txhubport(void __iomem *mbase, u8 epnum, ...@@ -439,15 +439,6 @@ static inline void musb_write_txhubport(void __iomem *mbase, u8 epnum,
/* Not implemented - HW has seperate Tx/Rx FIFO */ /* Not implemented - HW has seperate Tx/Rx FIFO */
#define MUSB_TXCSR_MODE 0x0000 #define MUSB_TXCSR_MODE 0x0000
/*
* Dummy stub for clk framework, it will be removed
* until Blackfin supports clk framework
*/
#define clk_get(dev, id) NULL
#define clk_put(clock) do {} while (0)
#define clk_enable(clock) do {} while (0)
#define clk_disable(clock) do {} while (0)
static inline void musb_write_txfifosz(void __iomem *mbase, u8 c_size) static inline void musb_write_txfifosz(void __iomem *mbase, u8 c_size)
{ {
} }
......
...@@ -554,13 +554,12 @@ static void aircable_throttle(struct tty_struct *tty) ...@@ -554,13 +554,12 @@ static void aircable_throttle(struct tty_struct *tty)
{ {
struct usb_serial_port *port = tty->driver_data; struct usb_serial_port *port = tty->driver_data;
struct aircable_private *priv = usb_get_serial_port_data(port); struct aircable_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
dbg("%s - port %d", __func__, port->number); dbg("%s - port %d", __func__, port->number);
spin_lock_irqsave(&priv->rx_lock, flags); spin_lock_irq(&priv->rx_lock);
priv->rx_flags |= THROTTLED; priv->rx_flags |= THROTTLED;
spin_unlock_irqrestore(&priv->rx_lock, flags); spin_unlock_irq(&priv->rx_lock);
} }
/* Based on ftdi_sio.c unthrottle */ /* Based on ftdi_sio.c unthrottle */
...@@ -569,14 +568,13 @@ static void aircable_unthrottle(struct tty_struct *tty) ...@@ -569,14 +568,13 @@ static void aircable_unthrottle(struct tty_struct *tty)
struct usb_serial_port *port = tty->driver_data; struct usb_serial_port *port = tty->driver_data;
struct aircable_private *priv = usb_get_serial_port_data(port); struct aircable_private *priv = usb_get_serial_port_data(port);
int actually_throttled; int actually_throttled;
unsigned long flags;
dbg("%s - port %d", __func__, port->number); dbg("%s - port %d", __func__, port->number);
spin_lock_irqsave(&priv->rx_lock, flags); spin_lock_irq(&priv->rx_lock);
actually_throttled = priv->rx_flags & ACTUALLY_THROTTLED; actually_throttled = priv->rx_flags & ACTUALLY_THROTTLED;
priv->rx_flags &= ~(THROTTLED | ACTUALLY_THROTTLED); priv->rx_flags &= ~(THROTTLED | ACTUALLY_THROTTLED);
spin_unlock_irqrestore(&priv->rx_lock, flags); spin_unlock_irq(&priv->rx_lock);
if (actually_throttled) if (actually_throttled)
schedule_work(&priv->rx_work); schedule_work(&priv->rx_work);
......
...@@ -113,6 +113,7 @@ static struct usb_device_id id_table [] = { ...@@ -113,6 +113,7 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(0x166A, 0x0303) }, /* Clipsal 5500PCU C-Bus USB interface */ { USB_DEVICE(0x166A, 0x0303) }, /* Clipsal 5500PCU C-Bus USB interface */
{ USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */ { USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */
{ USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */ { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */
{ USB_DEVICE(0x413C, 0x9500) }, /* DW700 GPS USB interface */
{ } /* Terminating Entry */ { } /* Terminating Entry */
}; };
......
...@@ -1155,13 +1155,12 @@ static void cypress_throttle(struct tty_struct *tty) ...@@ -1155,13 +1155,12 @@ static void cypress_throttle(struct tty_struct *tty)
{ {
struct usb_serial_port *port = tty->driver_data; struct usb_serial_port *port = tty->driver_data;
struct cypress_private *priv = usb_get_serial_port_data(port); struct cypress_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
dbg("%s - port %d", __func__, port->number); dbg("%s - port %d", __func__, port->number);
spin_lock_irqsave(&priv->lock, flags); spin_lock_irq(&priv->lock);
priv->rx_flags = THROTTLED; priv->rx_flags = THROTTLED;
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irq(&priv->lock);
} }
...@@ -1170,14 +1169,13 @@ static void cypress_unthrottle(struct tty_struct *tty) ...@@ -1170,14 +1169,13 @@ static void cypress_unthrottle(struct tty_struct *tty)
struct usb_serial_port *port = tty->driver_data; struct usb_serial_port *port = tty->driver_data;
struct cypress_private *priv = usb_get_serial_port_data(port); struct cypress_private *priv = usb_get_serial_port_data(port);
int actually_throttled, result; int actually_throttled, result;
unsigned long flags;
dbg("%s - port %d", __func__, port->number); dbg("%s - port %d", __func__, port->number);
spin_lock_irqsave(&priv->lock, flags); spin_lock_irq(&priv->lock);
actually_throttled = priv->rx_flags & ACTUALLY_THROTTLED; actually_throttled = priv->rx_flags & ACTUALLY_THROTTLED;
priv->rx_flags = 0; priv->rx_flags = 0;
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irq(&priv->lock);
if (!priv->comm_is_ok) if (!priv->comm_is_ok)
return; return;
...@@ -1185,7 +1183,7 @@ static void cypress_unthrottle(struct tty_struct *tty) ...@@ -1185,7 +1183,7 @@ static void cypress_unthrottle(struct tty_struct *tty)
if (actually_throttled) { if (actually_throttled) {
port->interrupt_in_urb->dev = port->serial->dev; port->interrupt_in_urb->dev = port->serial->dev;
result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
if (result) { if (result) {
dev_err(&port->dev, "%s - failed submitting read urb, " dev_err(&port->dev, "%s - failed submitting read urb, "
"error %d\n", __func__, result); "error %d\n", __func__, result);
......
...@@ -898,16 +898,16 @@ static void digi_rx_unthrottle(struct tty_struct *tty) ...@@ -898,16 +898,16 @@ static void digi_rx_unthrottle(struct tty_struct *tty)
spin_lock_irqsave(&priv->dp_port_lock, flags); spin_lock_irqsave(&priv->dp_port_lock, flags);
/* turn throttle off */
priv->dp_throttled = 0;
priv->dp_throttle_restart = 0;
/* restart read chain */ /* restart read chain */
if (priv->dp_throttle_restart) { if (priv->dp_throttle_restart) {
port->read_urb->dev = port->serial->dev; port->read_urb->dev = port->serial->dev;
ret = usb_submit_urb(port->read_urb, GFP_ATOMIC); ret = usb_submit_urb(port->read_urb, GFP_ATOMIC);
} }
/* turn throttle off */
priv->dp_throttled = 0;
priv->dp_throttle_restart = 0;
spin_unlock_irqrestore(&priv->dp_port_lock, flags); spin_unlock_irqrestore(&priv->dp_port_lock, flags);
if (ret) if (ret)
......
...@@ -391,7 +391,7 @@ static void empeg_unthrottle(struct tty_struct *tty) ...@@ -391,7 +391,7 @@ static void empeg_unthrottle(struct tty_struct *tty)
dbg("%s - port %d", __func__, port->number); dbg("%s - port %d", __func__, port->number);
port->read_urb->dev = port->serial->dev; port->read_urb->dev = port->serial->dev;
result = usb_submit_urb(port->read_urb, GFP_ATOMIC); result = usb_submit_urb(port->read_urb, GFP_KERNEL);
if (result) if (result)
dev_err(&port->dev, dev_err(&port->dev,
"%s - failed submitting read urb, error %d\n", "%s - failed submitting read urb, error %d\n",
......
This diff is collapsed.
...@@ -1390,14 +1390,13 @@ static void garmin_throttle(struct tty_struct *tty) ...@@ -1390,14 +1390,13 @@ static void garmin_throttle(struct tty_struct *tty)
{ {
struct usb_serial_port *port = tty->driver_data; struct usb_serial_port *port = tty->driver_data;
struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
unsigned long flags;
dbg("%s - port %d", __func__, port->number); dbg("%s - port %d", __func__, port->number);
/* set flag, data received will be put into a queue /* set flag, data received will be put into a queue
for later processing */ for later processing */
spin_lock_irqsave(&garmin_data_p->lock, flags); spin_lock_irq(&garmin_data_p->lock);
garmin_data_p->flags |= FLAGS_QUEUING|FLAGS_THROTTLED; garmin_data_p->flags |= FLAGS_QUEUING|FLAGS_THROTTLED;
spin_unlock_irqrestore(&garmin_data_p->lock, flags); spin_unlock_irq(&garmin_data_p->lock);
} }
...@@ -1405,13 +1404,12 @@ static void garmin_unthrottle(struct tty_struct *tty) ...@@ -1405,13 +1404,12 @@ static void garmin_unthrottle(struct tty_struct *tty)
{ {
struct usb_serial_port *port = tty->driver_data; struct usb_serial_port *port = tty->driver_data;
struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
unsigned long flags;
int status; int status;
dbg("%s - port %d", __func__, port->number); dbg("%s - port %d", __func__, port->number);
spin_lock_irqsave(&garmin_data_p->lock, flags); spin_lock_irq(&garmin_data_p->lock);
garmin_data_p->flags &= ~FLAGS_THROTTLED; garmin_data_p->flags &= ~FLAGS_THROTTLED;
spin_unlock_irqrestore(&garmin_data_p->lock, flags); spin_unlock_irq(&garmin_data_p->lock);
/* in native mode send queued data to tty, in /* in native mode send queued data to tty, in
serial mode nothing needs to be done here */ serial mode nothing needs to be done here */
...@@ -1419,7 +1417,7 @@ static void garmin_unthrottle(struct tty_struct *tty) ...@@ -1419,7 +1417,7 @@ static void garmin_unthrottle(struct tty_struct *tty)
garmin_flush_queue(garmin_data_p); garmin_flush_queue(garmin_data_p);
if (0 != (garmin_data_p->flags & FLAGS_BULK_IN_ACTIVE)) { if (0 != (garmin_data_p->flags & FLAGS_BULK_IN_ACTIVE)) {
status = usb_submit_urb(port->read_urb, GFP_ATOMIC); status = usb_submit_urb(port->read_urb, GFP_KERNEL);
if (status) if (status)
dev_err(&port->dev, dev_err(&port->dev,
"%s - failed resubmitting read urb, error %d\n", "%s - failed resubmitting read urb, error %d\n",
......
...@@ -546,7 +546,7 @@ void usb_serial_generic_unthrottle(struct tty_struct *tty) ...@@ -546,7 +546,7 @@ void usb_serial_generic_unthrottle(struct tty_struct *tty)
if (was_throttled) { if (was_throttled) {
/* Resume reading from device */ /* Resume reading from device */
usb_serial_generic_resubmit_read_urb(port, GFP_KERNEL); flush_and_resubmit_read_urb(port);
} }
} }
......
...@@ -966,6 +966,15 @@ static int ipaq_calc_num_ports(struct usb_serial *serial) ...@@ -966,6 +966,15 @@ static int ipaq_calc_num_ports(struct usb_serial *serial)
static int ipaq_startup(struct usb_serial *serial) static int ipaq_startup(struct usb_serial *serial)
{ {
dbg("%s", __func__); dbg("%s", __func__);
/* Some of the devices in ipaq_id_table[] are composite, and we
* shouldn't bind to all the interfaces. This test will rule out
* some obviously invalid possibilities.
*/
if (serial->num_bulk_in < serial->num_ports ||
serial->num_bulk_out < serial->num_ports)
return -ENODEV;
if (serial->dev->actconfig->desc.bConfigurationValue != 1) { if (serial->dev->actconfig->desc.bConfigurationValue != 1) {
/* /*
* FIXME: HP iPaq rx3715, possibly others, have 1 config that * FIXME: HP iPaq rx3715, possibly others, have 1 config that
......
...@@ -290,7 +290,7 @@ static void keyspan_pda_rx_unthrottle(struct tty_struct *tty) ...@@ -290,7 +290,7 @@ static void keyspan_pda_rx_unthrottle(struct tty_struct *tty)
/* just restart the receive interrupt URB */ /* just restart the receive interrupt URB */
dbg("keyspan_pda_rx_unthrottle port %d", port->number); dbg("keyspan_pda_rx_unthrottle port %d", port->number);
port->interrupt_in_urb->dev = port->serial->dev; port->interrupt_in_urb->dev = port->serial->dev;
if (usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC)) if (usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL))
dbg(" usb_submit_urb(read urb) failed"); dbg(" usb_submit_urb(read urb) failed");
return; return;
} }
......
...@@ -951,7 +951,7 @@ static void klsi_105_unthrottle(struct tty_struct *tty) ...@@ -951,7 +951,7 @@ static void klsi_105_unthrottle(struct tty_struct *tty)
dbg("%s - port %d", __func__, port->number); dbg("%s - port %d", __func__, port->number);
port->read_urb->dev = port->serial->dev; port->read_urb->dev = port->serial->dev;
result = usb_submit_urb(port->read_urb, GFP_ATOMIC); result = usb_submit_urb(port->read_urb, GFP_KERNEL);
if (result) if (result)
dev_err(&port->dev, dev_err(&port->dev,
"%s - failed submitting read urb, error %d\n", "%s - failed submitting read urb, error %d\n",
......
...@@ -777,20 +777,19 @@ static void mct_u232_throttle(struct tty_struct *tty) ...@@ -777,20 +777,19 @@ static void mct_u232_throttle(struct tty_struct *tty)
{ {
struct usb_serial_port *port = tty->driver_data; struct usb_serial_port *port = tty->driver_data;
struct mct_u232_private *priv = usb_get_serial_port_data(port); struct mct_u232_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
unsigned int control_state; unsigned int control_state;
dbg("%s - port %d", __func__, port->number); dbg("%s - port %d", __func__, port->number);
spin_lock_irqsave(&priv->lock, flags); spin_lock_irq(&priv->lock);
priv->rx_flags |= THROTTLED; priv->rx_flags |= THROTTLED;
if (C_CRTSCTS(tty)) { if (C_CRTSCTS(tty)) {
priv->control_state &= ~TIOCM_RTS; priv->control_state &= ~TIOCM_RTS;
control_state = priv->control_state; control_state = priv->control_state;
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irq(&priv->lock);
(void) mct_u232_set_modem_ctrl(port->serial, control_state); (void) mct_u232_set_modem_ctrl(port->serial, control_state);
} else { } else {
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irq(&priv->lock);
} }
} }
...@@ -799,20 +798,19 @@ static void mct_u232_unthrottle(struct tty_struct *tty) ...@@ -799,20 +798,19 @@ static void mct_u232_unthrottle(struct tty_struct *tty)
{ {
struct usb_serial_port *port = tty->driver_data; struct usb_serial_port *port = tty->driver_data;
struct mct_u232_private *priv = usb_get_serial_port_data(port); struct mct_u232_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
unsigned int control_state; unsigned int control_state;
dbg("%s - port %d", __func__, port->number); dbg("%s - port %d", __func__, port->number);
spin_lock_irqsave(&priv->lock, flags); spin_lock_irq(&priv->lock);
if ((priv->rx_flags & THROTTLED) && C_CRTSCTS(tty)) { if ((priv->rx_flags & THROTTLED) && C_CRTSCTS(tty)) {
priv->rx_flags &= ~THROTTLED; priv->rx_flags &= ~THROTTLED;
priv->control_state |= TIOCM_RTS; priv->control_state |= TIOCM_RTS;
control_state = priv->control_state; control_state = priv->control_state;
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irq(&priv->lock);
(void) mct_u232_set_modem_ctrl(port->serial, control_state); (void) mct_u232_set_modem_ctrl(port->serial, control_state);
} else { } else {
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irq(&priv->lock);
} }
} }
......
...@@ -314,21 +314,24 @@ static void opticon_unthrottle(struct tty_struct *tty) ...@@ -314,21 +314,24 @@ static void opticon_unthrottle(struct tty_struct *tty)
struct usb_serial_port *port = tty->driver_data; struct usb_serial_port *port = tty->driver_data;
struct opticon_private *priv = usb_get_serial_data(port->serial); struct opticon_private *priv = usb_get_serial_data(port->serial);
unsigned long flags; unsigned long flags;
int result; int result, was_throttled;
dbg("%s - port %d", __func__, port->number); dbg("%s - port %d", __func__, port->number);
spin_lock_irqsave(&priv->lock, flags); spin_lock_irqsave(&priv->lock, flags);
priv->throttled = false; priv->throttled = false;
was_throttled = priv->actually_throttled;
priv->actually_throttled = false; priv->actually_throttled = false;
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->lock, flags);
priv->bulk_read_urb->dev = port->serial->dev; priv->bulk_read_urb->dev = port->serial->dev;
result = usb_submit_urb(priv->bulk_read_urb, GFP_ATOMIC); if (was_throttled) {
if (result) result = usb_submit_urb(priv->bulk_read_urb, GFP_ATOMIC);
dev_err(&port->dev, if (result)
"%s - failed submitting read urb, error %d\n", dev_err(&port->dev,
"%s - failed submitting read urb, error %d\n",
__func__, result); __func__, result);
}
} }
static int opticon_tiocmget(struct tty_struct *tty, struct file *file) static int opticon_tiocmget(struct tty_struct *tty, struct file *file)
......
...@@ -165,6 +165,7 @@ static int option_resume(struct usb_serial *serial); ...@@ -165,6 +165,7 @@ static int option_resume(struct usb_serial *serial);
#define HUAWEI_PRODUCT_E143D 0x143D #define HUAWEI_PRODUCT_E143D 0x143D
#define HUAWEI_PRODUCT_E143E 0x143E #define HUAWEI_PRODUCT_E143E 0x143E
#define HUAWEI_PRODUCT_E143F 0x143F #define HUAWEI_PRODUCT_E143F 0x143F
#define HUAWEI_PRODUCT_E14AC 0x14AC
#define QUANTA_VENDOR_ID 0x0408 #define QUANTA_VENDOR_ID 0x0408
#define QUANTA_PRODUCT_Q101 0xEA02 #define QUANTA_PRODUCT_Q101 0xEA02
...@@ -318,6 +319,7 @@ static int option_resume(struct usb_serial *serial); ...@@ -318,6 +319,7 @@ static int option_resume(struct usb_serial *serial);
/* TOSHIBA PRODUCTS */ /* TOSHIBA PRODUCTS */
#define TOSHIBA_VENDOR_ID 0x0930 #define TOSHIBA_VENDOR_ID 0x0930
#define TOSHIBA_PRODUCT_HSDPA_MINICARD 0x1302 #define TOSHIBA_PRODUCT_HSDPA_MINICARD 0x1302
#define TOSHIBA_PRODUCT_G450 0x0d45
#define ALINK_VENDOR_ID 0x1e0e #define ALINK_VENDOR_ID 0x1e0e
#define ALINK_PRODUCT_3GU 0x9200 #define ALINK_PRODUCT_3GU 0x9200
...@@ -424,6 +426,7 @@ static struct usb_device_id option_ids[] = { ...@@ -424,6 +426,7 @@ static struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143D, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143D, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143E, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143E, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143F, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143F, 0xff, 0xff, 0xff) },
{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E14AC) },
{ USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_9508) }, { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_9508) },
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) }, /* Novatel Merlin V640/XV620 */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) }, /* Novatel Merlin V640/XV620 */
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) }, /* Novatel Merlin V620/S620 */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) }, /* Novatel Merlin V620/S620 */
...@@ -581,6 +584,7 @@ static struct usb_device_id option_ids[] = { ...@@ -581,6 +584,7 @@ static struct usb_device_id option_ids[] = {
{ USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H21_4523) }, { USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H21_4523) },
{ USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H20_4515) }, { USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H20_4515) },
{ USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H20_4519) }, { USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H20_4519) },
{ USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_G450) },
{ USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_HSDPA_MINICARD ) }, /* Toshiba 3G HSDPA == Novatel Expedite EU870D MiniCard */ { USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_HSDPA_MINICARD ) }, /* Toshiba 3G HSDPA == Novatel Expedite EU870D MiniCard */
{ USB_DEVICE(ALINK_VENDOR_ID, 0x9000) }, { USB_DEVICE(ALINK_VENDOR_ID, 0x9000) },
{ USB_DEVICE_AND_INTERFACE_INFO(ALINK_VENDOR_ID, ALINK_PRODUCT_3GU, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ALINK_VENDOR_ID, ALINK_PRODUCT_3GU, 0xff, 0xff, 0xff) },
......
...@@ -288,7 +288,7 @@ static void setup_line(struct work_struct *work) ...@@ -288,7 +288,7 @@ static void setup_line(struct work_struct *work)
dbg("%s(): submitting interrupt urb", __func__); dbg("%s(): submitting interrupt urb", __func__);
port->interrupt_in_urb->dev = port->serial->dev; port->interrupt_in_urb->dev = port->serial->dev;
result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
if (result != 0) { if (result != 0) {
dev_err(&port->dev, "%s(): usb_submit_urb() failed" dev_err(&port->dev, "%s(): usb_submit_urb() failed"
" with error %d\n", __func__, result); " with error %d\n", __func__, result);
...@@ -335,7 +335,7 @@ void send_data(struct work_struct *work) ...@@ -335,7 +335,7 @@ void send_data(struct work_struct *work)
dbg("%s(): submitting interrupt urb", __func__); dbg("%s(): submitting interrupt urb", __func__);
port->interrupt_in_urb->dev = port->serial->dev; port->interrupt_in_urb->dev = port->serial->dev;
result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); result = usb_submit_urb(port->interrupt_in_urb, GFP_NOIO);
if (result != 0) { if (result != 0) {
dev_err(&port->dev, "%s(): usb_submit_urb() failed" dev_err(&port->dev, "%s(): usb_submit_urb() failed"
" with error %d\n", __func__, result); " with error %d\n", __func__, result);
...@@ -349,7 +349,7 @@ void send_data(struct work_struct *work) ...@@ -349,7 +349,7 @@ void send_data(struct work_struct *work)
port->write_urb->transfer_buffer_length = count; port->write_urb->transfer_buffer_length = count;
port->write_urb->dev = port->serial->dev; port->write_urb->dev = port->serial->dev;
result = usb_submit_urb(port->write_urb, GFP_ATOMIC); result = usb_submit_urb(port->write_urb, GFP_NOIO);
if (result != 0) { if (result != 0) {
dev_err(&port->dev, "%s(): usb_submit_urb() failed" dev_err(&port->dev, "%s(): usb_submit_urb() failed"
" with error %d\n", __func__, result); " with error %d\n", __func__, result);
......
...@@ -1046,13 +1046,15 @@ static void pl2303_push_data(struct tty_struct *tty, ...@@ -1046,13 +1046,15 @@ static void pl2303_push_data(struct tty_struct *tty,
/* overrun is special, not associated with a char */ /* overrun is special, not associated with a char */
if (line_status & UART_OVERRUN_ERROR) if (line_status & UART_OVERRUN_ERROR)
tty_insert_flip_char(tty, 0, TTY_OVERRUN); tty_insert_flip_char(tty, 0, TTY_OVERRUN);
if (port->console && port->sysrq) {
if (tty_flag == TTY_NORMAL && !(port->console && port->sysrq))
tty_insert_flip_string(tty, data, urb->actual_length);
else {
int i; int i;
for (i = 0; i < urb->actual_length; ++i) for (i = 0; i < urb->actual_length; ++i)
if (!usb_serial_handle_sysrq_char(tty, port, data[i])) if (!usb_serial_handle_sysrq_char(tty, port, data[i]))
tty_insert_flip_char(tty, data[i], tty_flag); tty_insert_flip_char(tty, data[i], tty_flag);
} else }
tty_insert_flip_string(tty, data, urb->actual_length);
tty_flip_buffer_push(tty); tty_flip_buffer_push(tty);
} }
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
Whom based his on the Keyspan driver by Hugh Blemings <hugh@blemings.org> Whom based his on the Keyspan driver by Hugh Blemings <hugh@blemings.org>
*/ */
#define DRIVER_VERSION "v.1.3.7" #define DRIVER_VERSION "v.1.3.8"
#define DRIVER_AUTHOR "Kevin Lloyd, Elina Pasheva, Matthew Safar, Rory Filer" #define DRIVER_AUTHOR "Kevin Lloyd, Elina Pasheva, Matthew Safar, Rory Filer"
#define DRIVER_DESC "USB Driver for Sierra Wireless USB modems" #define DRIVER_DESC "USB Driver for Sierra Wireless USB modems"
......
...@@ -165,34 +165,36 @@ static void symbol_throttle(struct tty_struct *tty) ...@@ -165,34 +165,36 @@ static void symbol_throttle(struct tty_struct *tty)
{ {
struct usb_serial_port *port = tty->driver_data; struct usb_serial_port *port = tty->driver_data;
struct symbol_private *priv = usb_get_serial_data(port->serial); struct symbol_private *priv = usb_get_serial_data(port->serial);
unsigned long flags;
dbg("%s - port %d", __func__, port->number); dbg("%s - port %d", __func__, port->number);
spin_lock_irqsave(&priv->lock, flags); spin_lock_irq(&priv->lock);
priv->throttled = true; priv->throttled = true;
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irq(&priv->lock);
} }
static void symbol_unthrottle(struct tty_struct *tty) static void symbol_unthrottle(struct tty_struct *tty)
{ {
struct usb_serial_port *port = tty->driver_data; struct usb_serial_port *port = tty->driver_data;
struct symbol_private *priv = usb_get_serial_data(port->serial); struct symbol_private *priv = usb_get_serial_data(port->serial);
unsigned long flags;
int result; int result;
bool was_throttled;
dbg("%s - port %d", __func__, port->number); dbg("%s - port %d", __func__, port->number);
spin_lock_irqsave(&priv->lock, flags); spin_lock_irq(&priv->lock);
priv->throttled = false; priv->throttled = false;
was_throttled = priv->actually_throttled;
priv->actually_throttled = false; priv->actually_throttled = false;
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irq(&priv->lock);
priv->int_urb->dev = port->serial->dev; priv->int_urb->dev = port->serial->dev;
result = usb_submit_urb(priv->int_urb, GFP_ATOMIC); if (was_throttled) {
if (result) result = usb_submit_urb(priv->int_urb, GFP_KERNEL);
dev_err(&port->dev, if (result)
"%s - failed submitting read urb, error %d\n", dev_err(&port->dev,
"%s - failed submitting read urb, error %d\n",
__func__, result); __func__, result);
}
} }
static int symbol_startup(struct usb_serial *serial) static int symbol_startup(struct usb_serial *serial)
......
...@@ -156,7 +156,8 @@ static void destroy_serial(struct kref *kref) ...@@ -156,7 +156,8 @@ static void destroy_serial(struct kref *kref)
if (serial->minor != SERIAL_TTY_NO_MINOR) if (serial->minor != SERIAL_TTY_NO_MINOR)
return_serial(serial); return_serial(serial);
serial->type->release(serial); if (serial->attached)
serial->type->release(serial);
/* Now that nothing is using the ports, they can be freed */ /* Now that nothing is using the ports, they can be freed */
for (i = 0; i < serial->num_port_pointers; ++i) { for (i = 0; i < serial->num_port_pointers; ++i) {
...@@ -1059,12 +1060,15 @@ int usb_serial_probe(struct usb_interface *interface, ...@@ -1059,12 +1060,15 @@ int usb_serial_probe(struct usb_interface *interface,
module_put(type->driver.owner); module_put(type->driver.owner);
if (retval < 0) if (retval < 0)
goto probe_error; goto probe_error;
serial->attached = 1;
if (retval > 0) { if (retval > 0) {
/* quietly accept this device, but don't bind to a /* quietly accept this device, but don't bind to a
serial port as it's about to disappear */ serial port as it's about to disappear */
serial->num_ports = 0; serial->num_ports = 0;
goto exit; goto exit;
} }
} else {
serial->attached = 1;
} }
if (get_free_serial(serial, num_ports, &minor) == NULL) { if (get_free_serial(serial, num_ports, &minor) == NULL) {
...@@ -1164,8 +1168,10 @@ int usb_serial_suspend(struct usb_interface *intf, pm_message_t message) ...@@ -1164,8 +1168,10 @@ int usb_serial_suspend(struct usb_interface *intf, pm_message_t message)
if (serial->type->suspend) { if (serial->type->suspend) {
r = serial->type->suspend(serial, message); r = serial->type->suspend(serial, message);
if (r < 0) if (r < 0) {
serial->suspending = 0;
goto err_out; goto err_out;
}
} }
for (i = 0; i < serial->num_ports; ++i) { for (i = 0; i < serial->num_ports; ++i) {
......
...@@ -513,7 +513,8 @@ static void visor_read_bulk_callback(struct urb *urb) ...@@ -513,7 +513,8 @@ static void visor_read_bulk_callback(struct urb *urb)
tty_kref_put(tty); tty_kref_put(tty);
} }
spin_lock(&priv->lock); spin_lock(&priv->lock);
priv->bytes_in += available_room; if (tty)
priv->bytes_in += available_room;
} else { } else {
spin_lock(&priv->lock); spin_lock(&priv->lock);
...@@ -582,12 +583,11 @@ static void visor_throttle(struct tty_struct *tty) ...@@ -582,12 +583,11 @@ static void visor_throttle(struct tty_struct *tty)
{ {
struct usb_serial_port *port = tty->driver_data; struct usb_serial_port *port = tty->driver_data;
struct visor_private *priv = usb_get_serial_port_data(port); struct visor_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
dbg("%s - port %d", __func__, port->number); dbg("%s - port %d", __func__, port->number);
spin_lock_irqsave(&priv->lock, flags); spin_lock_irq(&priv->lock);
priv->throttled = 1; priv->throttled = 1;
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irq(&priv->lock);
} }
...@@ -595,21 +595,23 @@ static void visor_unthrottle(struct tty_struct *tty) ...@@ -595,21 +595,23 @@ static void visor_unthrottle(struct tty_struct *tty)
{ {
struct usb_serial_port *port = tty->driver_data; struct usb_serial_port *port = tty->driver_data;
struct visor_private *priv = usb_get_serial_port_data(port); struct visor_private *priv = usb_get_serial_port_data(port);
unsigned long flags; int result, was_throttled;
int result;
dbg("%s - port %d", __func__, port->number); dbg("%s - port %d", __func__, port->number);
spin_lock_irqsave(&priv->lock, flags); spin_lock_irq(&priv->lock);
priv->throttled = 0; priv->throttled = 0;
was_throttled = priv->actually_throttled;
priv->actually_throttled = 0; priv->actually_throttled = 0;
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irq(&priv->lock);
port->read_urb->dev = port->serial->dev; if (was_throttled) {
result = usb_submit_urb(port->read_urb, GFP_ATOMIC); port->read_urb->dev = port->serial->dev;
if (result) result = usb_submit_urb(port->read_urb, GFP_KERNEL);
dev_err(&port->dev, if (result)
"%s - failed submitting read urb, error %d\n", dev_err(&port->dev,
"%s - failed submitting read urb, error %d\n",
__func__, result); __func__, result);
}
} }
static int palm_os_3_probe(struct usb_serial *serial, static int palm_os_3_probe(struct usb_serial *serial,
......
...@@ -949,13 +949,12 @@ static void whiteheat_throttle(struct tty_struct *tty) ...@@ -949,13 +949,12 @@ static void whiteheat_throttle(struct tty_struct *tty)
{ {
struct usb_serial_port *port = tty->driver_data; struct usb_serial_port *port = tty->driver_data;
struct whiteheat_private *info = usb_get_serial_port_data(port); struct whiteheat_private *info = usb_get_serial_port_data(port);
unsigned long flags;
dbg("%s - port %d", __func__, port->number); dbg("%s - port %d", __func__, port->number);
spin_lock_irqsave(&info->lock, flags); spin_lock_irq(&info->lock);
info->flags |= THROTTLED; info->flags |= THROTTLED;
spin_unlock_irqrestore(&info->lock, flags); spin_unlock_irq(&info->lock);
return; return;
} }
...@@ -966,14 +965,13 @@ static void whiteheat_unthrottle(struct tty_struct *tty) ...@@ -966,14 +965,13 @@ static void whiteheat_unthrottle(struct tty_struct *tty)
struct usb_serial_port *port = tty->driver_data; struct usb_serial_port *port = tty->driver_data;
struct whiteheat_private *info = usb_get_serial_port_data(port); struct whiteheat_private *info = usb_get_serial_port_data(port);
int actually_throttled; int actually_throttled;
unsigned long flags;
dbg("%s - port %d", __func__, port->number); dbg("%s - port %d", __func__, port->number);
spin_lock_irqsave(&info->lock, flags); spin_lock_irq(&info->lock);
actually_throttled = info->flags & ACTUALLY_THROTTLED; actually_throttled = info->flags & ACTUALLY_THROTTLED;
info->flags &= ~(THROTTLED | ACTUALLY_THROTTLED); info->flags &= ~(THROTTLED | ACTUALLY_THROTTLED);
spin_unlock_irqrestore(&info->lock, flags); spin_unlock_irq(&info->lock);
if (actually_throttled) if (actually_throttled)
rx_data_softint(&info->rx_work); rx_data_softint(&info->rx_work);
......
...@@ -768,17 +768,32 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) ...@@ -768,17 +768,32 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
/* set the result so the higher layers expect this data */ /* set the result so the higher layers expect this data */
srb->result = SAM_STAT_CHECK_CONDITION; srb->result = SAM_STAT_CHECK_CONDITION;
/* If things are really okay, then let's show that. Zero /* We often get empty sense data. This could indicate that
* out the sense buffer so the higher layers won't realize * everything worked or that there was an unspecified
* we did an unsolicited auto-sense. */ * problem. We have to decide which.
if (result == USB_STOR_TRANSPORT_GOOD && */
/* Filemark 0, ignore EOM, ILI 0, no sense */ if ( /* Filemark 0, ignore EOM, ILI 0, no sense */
(srb->sense_buffer[2] & 0xaf) == 0 && (srb->sense_buffer[2] & 0xaf) == 0 &&
/* No ASC or ASCQ */ /* No ASC or ASCQ */
srb->sense_buffer[12] == 0 && srb->sense_buffer[12] == 0 &&
srb->sense_buffer[13] == 0) { srb->sense_buffer[13] == 0) {
srb->result = SAM_STAT_GOOD;
srb->sense_buffer[0] = 0x0; /* If things are really okay, then let's show that.
* Zero out the sense buffer so the higher layers
* won't realize we did an unsolicited auto-sense.
*/
if (result == USB_STOR_TRANSPORT_GOOD) {
srb->result = SAM_STAT_GOOD;
srb->sense_buffer[0] = 0x0;
/* If there was a problem, report an unspecified
* hardware error to prevent the higher layers from
* entering an infinite retry loop.
*/
} else {
srb->result = DID_ERROR << 16;
srb->sense_buffer[2] = HARDWARE_ERROR;
}
} }
} }
......
...@@ -1823,6 +1823,13 @@ UNUSUAL_DEV( 0x4102, 0x1020, 0x0100, 0x0100, ...@@ -1823,6 +1823,13 @@ UNUSUAL_DEV( 0x4102, 0x1020, 0x0100, 0x0100,
US_SC_DEVICE, US_PR_DEVICE, NULL, US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE ), US_FL_IGNORE_RESIDUE ),
/* Reported by Sergey Pinaev <dfo@antex.ru> */
UNUSUAL_DEV( 0x4102, 0x1059, 0x0000, 0x0000,
"iRiver",
"P7K",
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_MAX_SECTORS_64 ),
/* /*
* David Härdeman <david@2gen.com> * David Härdeman <david@2gen.com>
* The key makes the SCSI stack print confusing (but harmless) messages * The key makes the SCSI stack print confusing (but harmless) messages
......
...@@ -150,6 +150,7 @@ struct usb_serial { ...@@ -150,6 +150,7 @@ struct usb_serial {
struct usb_interface *interface; struct usb_interface *interface;
unsigned char disconnected:1; unsigned char disconnected:1;
unsigned char suspending:1; unsigned char suspending:1;
unsigned char attached:1;
unsigned char minor; unsigned char minor;
unsigned char num_ports; unsigned char num_ports;
unsigned char num_port_pointers; unsigned char num_port_pointers;
......
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