Commit 1d47091a authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'usb-3.7-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb

Pull USB fixes from Greg Kroah-Hartman:
 "Here are a bunch of USB fixes for the 3.7-rc tree.

  There's a lot of small USB serial driver fixes, and one larger one
  (the mos7840 driver changes are mostly just moving code around to fix
  problems.) Thanks to Johan Hovold for finding the problems and fixing
  them all up.

  Other than those, there is the usual new device ids, xhci bugfixes,
  and gadget driver fixes, nothing out of the ordinary.

  Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>"

* tag 'usb-3.7-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (49 commits)
  xhci: trivial: Remove assigned but unused ep_ctx.
  xhci: trivial: Remove assigned but unused slot_ctx.
  xhci: Fix missing break in xhci_evaluate_context_result.
  xhci: Fix potential NULL ptr deref in command cancellation.
  ehci: Add yet-another Lucid nohandoff pci quirk
  ehci: fix Lucid nohandoff pci quirk to be more generic with BIOS versions
  USB: mos7840: fix port_probe flow
  USB: mos7840: fix port-data memory leak
  USB: mos7840: remove invalid disconnect handling
  USB: mos7840: remove NULL-urb submission
  USB: qcserial: fix interface-data memory leak in error path
  USB: option: fix interface-data memory leak in error path
  USB: ipw: fix interface-data memory leak in error path
  USB: mos7840: fix port-device leak in error path
  USB: mos7840: fix urb leak at release
  USB: sierra: fix port-data memory leak
  USB: sierra: fix memory leak in probe error path
  USB: sierra: fix memory leak in attach error path
  USB: usb-wwan: fix multiple memory leaks in error paths
  USB: keyspan: fix NULL-pointer dereferences and memory leaks
  ...
parents 6ad2c73d 1d63f246
......@@ -739,13 +739,16 @@ static void hub_tt_work(struct work_struct *work)
int limit = 100;
spin_lock_irqsave (&hub->tt.lock, flags);
while (--limit && !list_empty (&hub->tt.clear_list)) {
while (!list_empty(&hub->tt.clear_list)) {
struct list_head *next;
struct usb_tt_clear *clear;
struct usb_device *hdev = hub->hdev;
const struct hc_driver *drv;
int status;
if (!hub->quiescing && --limit < 0)
break;
next = hub->tt.clear_list.next;
clear = list_entry (next, struct usb_tt_clear, clear_list);
list_del (&clear->clear_list);
......@@ -1210,7 +1213,7 @@ static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type)
if (hub->has_indicators)
cancel_delayed_work_sync(&hub->leds);
if (hub->tt.hub)
cancel_work_sync(&hub->tt.clear_work);
flush_work(&hub->tt.clear_work);
}
/* caller has locked the hub device */
......
......@@ -2069,8 +2069,10 @@ static irqreturn_t net2272_irq(int irq, void *_dev)
#if defined(PLX_PCI_RDK2)
/* see if PCI int for us by checking irqstat */
intcsr = readl(dev->rdk2.fpga_base_addr + RDK2_IRQSTAT);
if (!intcsr & (1 << NET2272_PCI_IRQ))
if (!intcsr & (1 << NET2272_PCI_IRQ)) {
spin_unlock(&dev->lock);
return IRQ_NONE;
}
/* check dma interrupts */
#endif
/* Platform/devcice interrupt handler */
......
......@@ -545,7 +545,14 @@ static const struct dmi_system_id __devinitconst ehci_dmi_nohandoff_table[] = {
/* Pegatron Lucid (Ordissimo AIRIS) */
.matches = {
DMI_MATCH(DMI_BOARD_NAME, "M11JB"),
DMI_MATCH(DMI_BIOS_VERSION, "Lucid-GE-133"),
DMI_MATCH(DMI_BIOS_VERSION, "Lucid-"),
},
},
{
/* Pegatron Lucid (Ordissimo) */
.matches = {
DMI_MATCH(DMI_BOARD_NAME, "Ordissimo"),
DMI_MATCH(DMI_BIOS_VERSION, "Lucid-"),
},
},
{ }
......
......@@ -544,7 +544,6 @@ void xhci_dbg_ctx(struct xhci_hcd *xhci,
int i;
/* Fields are 32 bits wide, DMA addresses are in bytes */
int field_size = 32 / 8;
struct xhci_slot_ctx *slot_ctx;
dma_addr_t dma = ctx->dma;
int csz = HCC_64BYTE_CONTEXT(xhci->hcc_params);
......@@ -570,7 +569,6 @@ void xhci_dbg_ctx(struct xhci_hcd *xhci,
dbg_rsvd64(xhci, (u64 *)ctrl_ctx, dma);
}
slot_ctx = xhci_get_slot_ctx(xhci, ctx);
xhci_dbg_slot_ctx(xhci, ctx);
xhci_dbg_ep_ctx(xhci, ctx, last_ep);
}
......@@ -151,9 +151,8 @@ static void xhci_usb3_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci,
if (portsc & PORT_DEV_REMOVE)
port_removable |= 1 << (i + 1);
}
memset(&desc->u.ss.DeviceRemovable,
(__force __u16) cpu_to_le16(port_removable),
sizeof(__u16));
desc->u.ss.DeviceRemovable = cpu_to_le16(port_removable);
}
static void xhci_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci,
......@@ -809,11 +808,13 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
temp = xhci_readl(xhci, port_array[wIndex]);
xhci_dbg(xhci, "set port power, actual port %d status = 0x%x\n", wIndex, temp);
spin_unlock_irqrestore(&xhci->lock, flags);
temp = usb_acpi_power_manageable(hcd->self.root_hub,
wIndex);
if (temp)
usb_acpi_set_power_state(hcd->self.root_hub,
wIndex, true);
spin_lock_irqsave(&xhci->lock, flags);
break;
case USB_PORT_FEAT_RESET:
temp = (temp | PORT_RESET);
......@@ -917,11 +918,13 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
xhci_writel(xhci, temp & ~PORT_POWER,
port_array[wIndex]);
spin_unlock_irqrestore(&xhci->lock, flags);
temp = usb_acpi_power_manageable(hcd->self.root_hub,
wIndex);
if (temp)
usb_acpi_set_power_state(hcd->self.root_hub,
wIndex, false);
spin_lock_irqsave(&xhci->lock, flags);
break;
default:
goto error;
......
......@@ -1228,6 +1228,17 @@ static void xhci_cmd_to_noop(struct xhci_hcd *xhci, struct xhci_cd *cur_cd)
cur_seg = find_trb_seg(xhci->cmd_ring->first_seg,
xhci->cmd_ring->dequeue, &cycle_state);
if (!cur_seg) {
xhci_warn(xhci, "Command ring mismatch, dequeue = %p %llx (dma)\n",
xhci->cmd_ring->dequeue,
(unsigned long long)
xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg,
xhci->cmd_ring->dequeue));
xhci_debug_ring(xhci, xhci->cmd_ring);
xhci_dbg_ring_ptrs(xhci, xhci->cmd_ring);
return;
}
/* find the command trb matched by cd from command ring */
for (cmd_trb = xhci->cmd_ring->dequeue;
cmd_trb != xhci->cmd_ring->enqueue;
......
......@@ -1627,7 +1627,6 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
struct xhci_hcd *xhci;
struct xhci_container_ctx *in_ctx, *out_ctx;
unsigned int ep_index;
struct xhci_ep_ctx *ep_ctx;
struct xhci_slot_ctx *slot_ctx;
struct xhci_input_control_ctx *ctrl_ctx;
u32 added_ctxs;
......@@ -1663,7 +1662,6 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
out_ctx = virt_dev->out_ctx;
ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx);
ep_index = xhci_get_endpoint_index(&ep->desc);
ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index);
/* If this endpoint is already in use, and the upper layers are trying
* to add it again without dropping it, reject the addition.
......@@ -1817,6 +1815,8 @@ static int xhci_evaluate_context_result(struct xhci_hcd *xhci,
case COMP_EBADSLT:
dev_warn(&udev->dev, "WARN: slot not enabled for"
"evaluate context command.\n");
ret = -EINVAL;
break;
case COMP_CTX_STATE:
dev_warn(&udev->dev, "WARN: invalid context state for "
"evaluate context command.\n");
......@@ -4021,7 +4021,7 @@ int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev)
static unsigned long long xhci_service_interval_to_ns(
struct usb_endpoint_descriptor *desc)
{
return (1 << (desc->bInterval - 1)) * 125 * 1000;
return (1ULL << (desc->bInterval - 1)) * 125 * 1000;
}
static u16 xhci_get_timeout_no_hub_lpm(struct usb_device *udev,
......@@ -4142,7 +4142,7 @@ static u16 xhci_calculate_intel_u2_timeout(struct usb_device *udev,
(xhci_service_interval_to_ns(desc) > timeout_ns))
timeout_ns = xhci_service_interval_to_ns(desc);
u2_del_ns = udev->bos->ss_cap->bU2DevExitLat * 1000;
u2_del_ns = le16_to_cpu(udev->bos->ss_cap->bU2DevExitLat) * 1000ULL;
if (u2_del_ns > timeout_ns)
timeout_ns = u2_del_ns;
......
......@@ -158,3 +158,4 @@ int ezusb_fx2_ihex_firmware_download(struct usb_device *dev,
}
EXPORT_SYMBOL_GPL(ezusb_fx2_ihex_firmware_download);
MODULE_LICENSE("GPL");
......@@ -458,11 +458,11 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)
struct platform_device *musb;
struct resource *res;
struct resource resources[2];
char res_name[10];
char res_name[11];
int ret, musbid;
/* get memory resource */
sprintf(res_name, "musb%d", id);
snprintf(res_name, sizeof(res_name), "musb%d", id);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, res_name);
if (!res) {
dev_err(dev, "%s get mem resource failed\n", res_name);
......@@ -473,7 +473,7 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)
resources[0] = *res;
/* get irq resource */
sprintf(res_name, "musb%d-irq", id);
snprintf(res_name, sizeof(res_name), "musb%d-irq", id);
res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, res_name);
if (!res) {
dev_err(dev, "%s get irq resource failed\n", res_name);
......@@ -530,7 +530,7 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)
of_property_read_u32(np, "num-eps", (u32 *)&config->num_eps);
of_property_read_u32(np, "ram-bits", (u32 *)&config->ram_bits);
sprintf(res_name, "port%d-mode", id);
snprintf(res_name, sizeof(res_name), "port%d-mode", id);
of_property_read_u32(np, res_name, (u32 *)&pdata->mode);
of_property_read_u32(np, "power", (u32 *)&pdata->power);
config->multipoint = of_property_read_bool(np, "multipoint");
......
......@@ -795,6 +795,7 @@ static void xfer_work(struct work_struct *work)
dev_dbg(dev, " %s %d (%d/ %d)\n",
fifo->name, usbhs_pipe_number(pipe), pkt->length, pkt->zero);
usbhs_pipe_enable(pipe);
usbhsf_dma_start(pipe, fifo);
dma_async_issue_pending(chan);
}
......
......@@ -334,6 +334,11 @@ static void usbhsh_pipe_detach(struct usbhsh_hpriv *hpriv,
struct device *dev = usbhs_priv_to_dev(priv);
unsigned long flags;
if (unlikely(!uep)) {
dev_err(dev, "no uep\n");
return;
}
/******************** spin lock ********************/
usbhs_lock(priv, flags);
......
......@@ -242,13 +242,11 @@ out: kfree(buffer);
return r;
}
/* allocate private data */
static int ch341_attach(struct usb_serial *serial)
static int ch341_port_probe(struct usb_serial_port *port)
{
struct ch341_private *priv;
int r;
/* private data */
priv = kzalloc(sizeof(struct ch341_private), GFP_KERNEL);
if (!priv)
return -ENOMEM;
......@@ -258,17 +256,27 @@ static int ch341_attach(struct usb_serial *serial)
priv->baud_rate = DEFAULT_BAUD_RATE;
priv->line_control = CH341_BIT_RTS | CH341_BIT_DTR;
r = ch341_configure(serial->dev, priv);
r = ch341_configure(port->serial->dev, priv);
if (r < 0)
goto error;
usb_set_serial_port_data(serial->port[0], priv);
usb_set_serial_port_data(port, priv);
return 0;
error: kfree(priv);
return r;
}
static int ch341_port_remove(struct usb_serial_port *port)
{
struct ch341_private *priv;
priv = usb_get_serial_port_data(port);
kfree(priv);
return 0;
}
static int ch341_carrier_raised(struct usb_serial_port *port)
{
struct ch341_private *priv = usb_get_serial_port_data(port);
......@@ -304,7 +312,7 @@ static void ch341_close(struct usb_serial_port *port)
static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port)
{
struct usb_serial *serial = port->serial;
struct ch341_private *priv = usb_get_serial_port_data(serial->port[0]);
struct ch341_private *priv = usb_get_serial_port_data(port);
int r;
priv->baud_rate = DEFAULT_BAUD_RATE;
......@@ -608,7 +616,8 @@ static struct usb_serial_driver ch341_device = {
.tiocmget = ch341_tiocmget,
.tiocmset = ch341_tiocmset,
.read_int_callback = ch341_read_int_callback,
.attach = ch341_attach,
.port_probe = ch341_port_probe,
.port_remove = ch341_port_remove,
.reset_resume = ch341_reset_resume,
};
......
......@@ -244,6 +244,8 @@ static int digi_startup_device(struct usb_serial *serial);
static int digi_startup(struct usb_serial *serial);
static void digi_disconnect(struct usb_serial *serial);
static void digi_release(struct usb_serial *serial);
static int digi_port_probe(struct usb_serial_port *port);
static int digi_port_remove(struct usb_serial_port *port);
static void digi_read_bulk_callback(struct urb *urb);
static int digi_read_inb_callback(struct urb *urb);
static int digi_read_oob_callback(struct urb *urb);
......@@ -294,6 +296,8 @@ static struct usb_serial_driver digi_acceleport_2_device = {
.attach = digi_startup,
.disconnect = digi_disconnect,
.release = digi_release,
.port_probe = digi_port_probe,
.port_remove = digi_port_remove,
};
static struct usb_serial_driver digi_acceleport_4_device = {
......@@ -320,6 +324,8 @@ static struct usb_serial_driver digi_acceleport_4_device = {
.attach = digi_startup,
.disconnect = digi_disconnect,
.release = digi_release,
.port_probe = digi_port_probe,
.port_remove = digi_port_remove,
};
static struct usb_serial_driver * const serial_drivers[] = {
......@@ -1240,59 +1246,50 @@ static int digi_startup_device(struct usb_serial *serial)
return ret;
}
static int digi_startup(struct usb_serial *serial)
static int digi_port_init(struct usb_serial_port *port, unsigned port_num)
{
int i;
struct digi_port *priv;
struct digi_serial *serial_priv;
/* allocate the private data structures for all ports */
/* number of regular ports + 1 for the out-of-band port */
for (i = 0; i < serial->type->num_ports + 1; i++) {
/* allocate port private structure */
priv = kmalloc(sizeof(struct digi_port), GFP_KERNEL);
if (priv == NULL) {
while (--i >= 0)
kfree(usb_get_serial_port_data(serial->port[i]));
return 1; /* error */
}
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
/* initialize port private structure */
spin_lock_init(&priv->dp_port_lock);
priv->dp_port_num = i;
priv->dp_out_buf_len = 0;
priv->dp_write_urb_in_use = 0;
priv->dp_modem_signals = 0;
priv->dp_port_num = port_num;
init_waitqueue_head(&priv->dp_modem_change_wait);
priv->dp_transmit_idle = 0;
init_waitqueue_head(&priv->dp_transmit_idle_wait);
priv->dp_throttled = 0;
priv->dp_throttle_restart = 0;
init_waitqueue_head(&priv->dp_flush_wait);
init_waitqueue_head(&priv->dp_close_wait);
INIT_WORK(&priv->dp_wakeup_work, digi_wakeup_write_lock);
priv->dp_port = serial->port[i];
/* initialize write wait queue for this port */
init_waitqueue_head(&serial->port[i]->write_wait);
priv->dp_port = port;
usb_set_serial_port_data(serial->port[i], priv);
}
init_waitqueue_head(&port->write_wait);
/* allocate serial private structure */
serial_priv = kmalloc(sizeof(struct digi_serial), GFP_KERNEL);
if (serial_priv == NULL) {
for (i = 0; i < serial->type->num_ports + 1; i++)
kfree(usb_get_serial_port_data(serial->port[i]));
return 1; /* error */
}
usb_set_serial_port_data(port, priv);
return 0;
}
static int digi_startup(struct usb_serial *serial)
{
struct digi_serial *serial_priv;
int ret;
serial_priv = kzalloc(sizeof(*serial_priv), GFP_KERNEL);
if (!serial_priv)
return -ENOMEM;
/* initialize serial private structure */
spin_lock_init(&serial_priv->ds_serial_lock);
serial_priv->ds_oob_port_num = serial->type->num_ports;
serial_priv->ds_oob_port = serial->port[serial_priv->ds_oob_port_num];
serial_priv->ds_device_started = 0;
ret = digi_port_init(serial_priv->ds_oob_port,
serial_priv->ds_oob_port_num);
if (ret) {
kfree(serial_priv);
return ret;
}
usb_set_serial_data(serial, serial_priv);
return 0;
......@@ -1313,15 +1310,35 @@ static void digi_disconnect(struct usb_serial *serial)
static void digi_release(struct usb_serial *serial)
{
int i;
struct digi_serial *serial_priv;
struct digi_port *priv;
serial_priv = usb_get_serial_data(serial);
priv = usb_get_serial_port_data(serial_priv->ds_oob_port);
kfree(priv);
kfree(serial_priv);
}
static int digi_port_probe(struct usb_serial_port *port)
{
unsigned port_num;
/* free the private data structures for all ports */
/* number of regular ports + 1 for the out-of-band port */
for (i = 0; i < serial->type->num_ports + 1; i++)
kfree(usb_get_serial_port_data(serial->port[i]));
kfree(usb_get_serial_data(serial));
port_num = port->number - port->serial->minor;
return digi_port_init(port, port_num);
}
static int digi_port_remove(struct usb_serial_port *port)
{
struct digi_port *priv;
priv = usb_get_serial_port_data(port);
kfree(priv);
return 0;
}
static void digi_read_bulk_callback(struct urb *urb)
{
......
......@@ -203,8 +203,7 @@ static int ipw_open(struct tty_struct *tty, struct usb_serial_port *port)
return 0;
}
/* fake probe - only to allocate data structures */
static int ipw_probe(struct usb_serial *serial, const struct usb_device_id *id)
static int ipw_attach(struct usb_serial *serial)
{
struct usb_wwan_intf_private *data;
......@@ -303,9 +302,9 @@ static struct usb_serial_driver ipw_device = {
.num_ports = 1,
.open = ipw_open,
.close = ipw_close,
.probe = ipw_probe,
.attach = usb_wwan_startup,
.attach = ipw_attach,
.release = ipw_release,
.port_probe = usb_wwan_port_probe,
.port_remove = usb_wwan_port_remove,
.dtr_rts = ipw_dtr_rts,
.write = usb_wwan_write,
......
......@@ -1374,13 +1374,9 @@ static struct callbacks {
data in device_details */
static void keyspan_setup_urbs(struct usb_serial *serial)
{
int i, j;
struct keyspan_serial_private *s_priv;
const struct keyspan_device_details *d_details;
struct usb_serial_port *port;
struct keyspan_port_private *p_priv;
struct callbacks *cback;
int endp;
s_priv = usb_get_serial_data(serial);
d_details = s_priv->device_details;
......@@ -1404,45 +1400,6 @@ static void keyspan_setup_urbs(struct usb_serial *serial)
(serial, d_details->glocont_endpoint, USB_DIR_OUT,
serial, s_priv->glocont_buf, GLOCONT_BUFLEN,
cback->glocont_callback);
/* Setup endpoints for each port specific thing */
for (i = 0; i < d_details->num_ports; i++) {
port = serial->port[i];
p_priv = usb_get_serial_port_data(port);
/* Do indat endpoints first, once for each flip */
endp = d_details->indat_endpoints[i];
for (j = 0; j <= d_details->indat_endp_flip; ++j, ++endp) {
p_priv->in_urbs[j] = keyspan_setup_urb
(serial, endp, USB_DIR_IN, port,
p_priv->in_buffer[j], 64,
cback->indat_callback);
}
for (; j < 2; ++j)
p_priv->in_urbs[j] = NULL;
/* outdat endpoints also have flip */
endp = d_details->outdat_endpoints[i];
for (j = 0; j <= d_details->outdat_endp_flip; ++j, ++endp) {
p_priv->out_urbs[j] = keyspan_setup_urb
(serial, endp, USB_DIR_OUT, port,
p_priv->out_buffer[j], 64,
cback->outdat_callback);
}
for (; j < 2; ++j)
p_priv->out_urbs[j] = NULL;
/* inack endpoint */
p_priv->inack_urb = keyspan_setup_urb
(serial, d_details->inack_endpoints[i], USB_DIR_IN,
port, p_priv->inack_buffer, 1, cback->inack_callback);
/* outcont endpoint */
p_priv->outcont_urb = keyspan_setup_urb
(serial, d_details->outcont_endpoints[i], USB_DIR_OUT,
port, p_priv->outcont_buffer, 64,
cback->outcont_callback);
}
}
/* usa19 function doesn't require prescaler */
......@@ -2407,9 +2364,7 @@ static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)
static int keyspan_startup(struct usb_serial *serial)
{
int i, err;
struct usb_serial_port *port;
struct keyspan_serial_private *s_priv;
struct keyspan_port_private *p_priv;
const struct keyspan_device_details *d_details;
for (i = 0; (d_details = keyspan_devices[i]) != NULL; ++i)
......@@ -2432,19 +2387,6 @@ static int keyspan_startup(struct usb_serial *serial)
s_priv->device_details = d_details;
usb_set_serial_data(serial, s_priv);
/* Now setup per port private data */
for (i = 0; i < serial->num_ports; i++) {
port = serial->port[i];
p_priv = kzalloc(sizeof(struct keyspan_port_private),
GFP_KERNEL);
if (!p_priv) {
dev_dbg(&port->dev, "%s - kmalloc for keyspan_port_private (%d) failed!.\n", __func__, i);
return 1;
}
p_priv->device_details = d_details;
usb_set_serial_port_data(port, p_priv);
}
keyspan_setup_urbs(serial);
if (s_priv->instat_urb != NULL) {
......@@ -2463,59 +2405,112 @@ static int keyspan_startup(struct usb_serial *serial)
static void keyspan_disconnect(struct usb_serial *serial)
{
int i, j;
struct usb_serial_port *port;
struct keyspan_serial_private *s_priv;
struct keyspan_port_private *p_priv;
s_priv = usb_get_serial_data(serial);
/* Stop reading/writing urbs */
stop_urb(s_priv->instat_urb);
stop_urb(s_priv->glocont_urb);
stop_urb(s_priv->indat_urb);
for (i = 0; i < serial->num_ports; ++i) {
port = serial->port[i];
p_priv = usb_get_serial_port_data(port);
stop_urb(p_priv->inack_urb);
stop_urb(p_priv->outcont_urb);
for (j = 0; j < 2; j++) {
stop_urb(p_priv->in_urbs[j]);
stop_urb(p_priv->out_urbs[j]);
}
}
}
static void keyspan_release(struct usb_serial *serial)
{
struct keyspan_serial_private *s_priv;
s_priv = usb_get_serial_data(serial);
/* Now free them */
usb_free_urb(s_priv->instat_urb);
usb_free_urb(s_priv->indat_urb);
usb_free_urb(s_priv->glocont_urb);
for (i = 0; i < serial->num_ports; ++i) {
port = serial->port[i];
p_priv = usb_get_serial_port_data(port);
usb_free_urb(p_priv->inack_urb);
usb_free_urb(p_priv->outcont_urb);
for (j = 0; j < 2; j++) {
usb_free_urb(p_priv->in_urbs[j]);
usb_free_urb(p_priv->out_urbs[j]);
kfree(s_priv);
}
static int keyspan_port_probe(struct usb_serial_port *port)
{
struct usb_serial *serial = port->serial;
struct keyspan_port_private *s_priv;
struct keyspan_port_private *p_priv;
const struct keyspan_device_details *d_details;
struct callbacks *cback;
int endp;
int port_num;
int i;
s_priv = usb_get_serial_data(serial);
d_details = s_priv->device_details;
p_priv = kzalloc(sizeof(*p_priv), GFP_KERNEL);
if (!p_priv)
return -ENOMEM;
s_priv = usb_get_serial_data(port->serial);
p_priv->device_details = d_details;
/* Setup values for the various callback routines */
cback = &keyspan_callbacks[d_details->msg_format];
port_num = port->number - port->serial->minor;
/* Do indat endpoints first, once for each flip */
endp = d_details->indat_endpoints[port_num];
for (i = 0; i <= d_details->indat_endp_flip; ++i, ++endp) {
p_priv->in_urbs[i] = keyspan_setup_urb(serial, endp,
USB_DIR_IN, port,
p_priv->in_buffer[i], 64,
cback->indat_callback);
}
/* outdat endpoints also have flip */
endp = d_details->outdat_endpoints[port_num];
for (i = 0; i <= d_details->outdat_endp_flip; ++i, ++endp) {
p_priv->out_urbs[i] = keyspan_setup_urb(serial, endp,
USB_DIR_OUT, port,
p_priv->out_buffer[i], 64,
cback->outdat_callback);
}
/* inack endpoint */
p_priv->inack_urb = keyspan_setup_urb(serial,
d_details->inack_endpoints[port_num],
USB_DIR_IN, port,
p_priv->inack_buffer, 1,
cback->inack_callback);
/* outcont endpoint */
p_priv->outcont_urb = keyspan_setup_urb(serial,
d_details->outcont_endpoints[port_num],
USB_DIR_OUT, port,
p_priv->outcont_buffer, 64,
cback->outcont_callback);
usb_set_serial_port_data(port, p_priv);
return 0;
}
static void keyspan_release(struct usb_serial *serial)
static int keyspan_port_remove(struct usb_serial_port *port)
{
struct keyspan_port_private *p_priv;
int i;
struct usb_serial_port *port;
struct keyspan_serial_private *s_priv;
s_priv = usb_get_serial_data(serial);
p_priv = usb_get_serial_port_data(port);
kfree(s_priv);
stop_urb(p_priv->inack_urb);
stop_urb(p_priv->outcont_urb);
for (i = 0; i < 2; i++) {
stop_urb(p_priv->in_urbs[i]);
stop_urb(p_priv->out_urbs[i]);
}
/* Now free per port private data */
for (i = 0; i < serial->num_ports; i++) {
port = serial->port[i];
kfree(usb_get_serial_port_data(port));
usb_free_urb(p_priv->inack_urb);
usb_free_urb(p_priv->outcont_urb);
for (i = 0; i < 2; i++) {
usb_free_urb(p_priv->in_urbs[i]);
usb_free_urb(p_priv->out_urbs[i]);
}
kfree(p_priv);
return 0;
}
MODULE_AUTHOR(DRIVER_AUTHOR);
......
......@@ -42,6 +42,8 @@ static void keyspan_dtr_rts (struct usb_serial_port *port, int on);
static int keyspan_startup (struct usb_serial *serial);
static void keyspan_disconnect (struct usb_serial *serial);
static void keyspan_release (struct usb_serial *serial);
static int keyspan_port_probe(struct usb_serial_port *port);
static int keyspan_port_remove(struct usb_serial_port *port);
static int keyspan_write_room (struct tty_struct *tty);
static int keyspan_write (struct tty_struct *tty,
......@@ -567,6 +569,8 @@ static struct usb_serial_driver keyspan_1port_device = {
.attach = keyspan_startup,
.disconnect = keyspan_disconnect,
.release = keyspan_release,
.port_probe = keyspan_port_probe,
.port_remove = keyspan_port_remove,
};
static struct usb_serial_driver keyspan_2port_device = {
......@@ -589,6 +593,8 @@ static struct usb_serial_driver keyspan_2port_device = {
.attach = keyspan_startup,
.disconnect = keyspan_disconnect,
.release = keyspan_release,
.port_probe = keyspan_port_probe,
.port_remove = keyspan_port_remove,
};
static struct usb_serial_driver keyspan_4port_device = {
......@@ -611,6 +617,8 @@ static struct usb_serial_driver keyspan_4port_device = {
.attach = keyspan_startup,
.disconnect = keyspan_disconnect,
.release = keyspan_release,
.port_probe = keyspan_port_probe,
.port_remove = keyspan_port_remove,
};
static struct usb_serial_driver * const serial_drivers[] = {
......
......@@ -49,7 +49,8 @@
* Function prototypes
*/
static int mct_u232_startup(struct usb_serial *serial);
static void mct_u232_release(struct usb_serial *serial);
static int mct_u232_port_probe(struct usb_serial_port *port);
static int mct_u232_port_remove(struct usb_serial_port *remove);
static int mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port);
static void mct_u232_close(struct usb_serial_port *port);
static void mct_u232_dtr_rts(struct usb_serial_port *port, int on);
......@@ -99,7 +100,8 @@ static struct usb_serial_driver mct_u232_device = {
.tiocmget = mct_u232_tiocmget,
.tiocmset = mct_u232_tiocmset,
.attach = mct_u232_startup,
.release = mct_u232_release,
.port_probe = mct_u232_port_probe,
.port_remove = mct_u232_port_remove,
.ioctl = mct_u232_ioctl,
.get_icount = mct_u232_get_icount,
};
......@@ -388,18 +390,8 @@ static void mct_u232_msr_to_state(struct usb_serial_port *port,
static int mct_u232_startup(struct usb_serial *serial)
{
struct mct_u232_private *priv;
struct usb_serial_port *port, *rport;
priv = kzalloc(sizeof(struct mct_u232_private), GFP_KERNEL);
if (!priv)
return -ENOMEM;
spin_lock_init(&priv->lock);
init_waitqueue_head(&priv->msr_wait);
usb_set_serial_port_data(serial->port[0], priv);
init_waitqueue_head(&serial->port[0]->write_wait);
/* Puh, that's dirty */
port = serial->port[0];
rport = serial->port[1];
......@@ -412,18 +404,31 @@ static int mct_u232_startup(struct usb_serial *serial)
return 0;
} /* mct_u232_startup */
static int mct_u232_port_probe(struct usb_serial_port *port)
{
struct mct_u232_private *priv;
static void mct_u232_release(struct usb_serial *serial)
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
spin_lock_init(&priv->lock);
init_waitqueue_head(&priv->msr_wait);
usb_set_serial_port_data(port, priv);
return 0;
}
static int mct_u232_port_remove(struct usb_serial_port *port)
{
struct mct_u232_private *priv;
int i;
for (i = 0; i < serial->num_ports; ++i) {
/* My special items, the standard routines free my urbs */
priv = usb_get_serial_port_data(serial->port[i]);
priv = usb_get_serial_port_data(port);
kfree(priv);
}
} /* mct_u232_release */
return 0;
}
static int mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port)
{
......@@ -515,12 +520,14 @@ static void mct_u232_dtr_rts(struct usb_serial_port *port, int on)
static void mct_u232_close(struct usb_serial_port *port)
{
if (port->serial->dev) {
/* shutdown our urbs */
usb_kill_urb(port->write_urb);
/*
* Must kill the read urb as it is actually an interrupt urb, which
* generic close thus fails to kill.
*/
usb_kill_urb(port->read_urb);
usb_kill_urb(port->interrupt_in_urb);
}
usb_serial_generic_close(port);
} /* mct_u232_close */
......
......@@ -179,16 +179,13 @@ static void metrousb_cleanup(struct usb_serial_port *port)
{
dev_dbg(&port->dev, "%s\n", __func__);
if (port->serial->dev) {
/* Shutdown any interrupt in urbs. */
if (port->interrupt_in_urb) {
usb_unlink_urb(port->interrupt_in_urb);
usb_kill_urb(port->interrupt_in_urb);
}
/* Send deactivate cmd to device */
mutex_lock(&port->serial->disc_mutex);
if (!port->serial->disconnected)
metrousb_send_unidirectional_cmd(UNI_CMD_CLOSE, port);
}
mutex_unlock(&port->serial->disc_mutex);
}
static int metrousb_open(struct tty_struct *tty, struct usb_serial_port *port)
......@@ -271,51 +268,27 @@ static int metrousb_set_modem_ctrl(struct usb_serial *serial, unsigned int contr
return retval;
}
static void metrousb_shutdown(struct usb_serial *serial)
static int metrousb_port_probe(struct usb_serial_port *port)
{
int i = 0;
struct metrousb_private *metro_priv;
dev_dbg(&serial->dev->dev, "%s\n", __func__);
metro_priv = kzalloc(sizeof(*metro_priv), GFP_KERNEL);
if (!metro_priv)
return -ENOMEM;
/* Stop reading and writing on all ports. */
for (i = 0; i < serial->num_ports; ++i) {
/* Close any open urbs. */
metrousb_cleanup(serial->port[i]);
spin_lock_init(&metro_priv->lock);
/* Free memory. */
kfree(usb_get_serial_port_data(serial->port[i]));
usb_set_serial_port_data(serial->port[i], NULL);
usb_set_serial_port_data(port, metro_priv);
dev_dbg(&serial->dev->dev, "%s - freed port number=%d\n",
__func__, serial->port[i]->number);
}
return 0;
}
static int metrousb_startup(struct usb_serial *serial)
static int metrousb_port_remove(struct usb_serial_port *port)
{
struct metrousb_private *metro_priv;
struct usb_serial_port *port;
int i = 0;
dev_dbg(&serial->dev->dev, "%s\n", __func__);
/* Loop through the serial ports setting up the private structures.
* Currently we only use one port. */
for (i = 0; i < serial->num_ports; ++i) {
port = serial->port[i];
/* Declare memory. */
metro_priv = kzalloc(sizeof(struct metrousb_private), GFP_KERNEL);
if (!metro_priv)
return -ENOMEM;
/* Initialize memory. */
spin_lock_init(&metro_priv->lock);
usb_set_serial_port_data(port, metro_priv);
dev_dbg(&serial->dev->dev, "%s - port number=%d\n ",
__func__, port->number);
}
metro_priv = usb_get_serial_port_data(port);
kfree(metro_priv);
return 0;
}
......@@ -414,8 +387,8 @@ static struct usb_serial_driver metrousb_device = {
.close = metrousb_cleanup,
.read_int_callback = metrousb_read_int_callback,
.write_int_callback = metrousb_write_int_callback,
.attach = metrousb_startup,
.release = metrousb_shutdown,
.port_probe = metrousb_port_probe,
.port_remove = metrousb_port_remove,
.throttle = metrousb_throttle,
.unthrottle = metrousb_unthrottle,
.tiocmget = metrousb_tiocmget,
......
......@@ -1966,9 +1966,7 @@ static int mos7720_ioctl(struct tty_struct *tty,
static int mos7720_startup(struct usb_serial *serial)
{
struct moschip_port *mos7720_port;
struct usb_device *dev;
int i;
char data;
u16 product;
int ret_val;
......@@ -1999,29 +1997,6 @@ static int mos7720_startup(struct usb_serial *serial)
serial->port[1]->interrupt_in_buffer = NULL;
}
/* set up serial port private structures */
for (i = 0; i < serial->num_ports; ++i) {
mos7720_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL);
if (mos7720_port == NULL) {
dev_err(&dev->dev, "%s - Out of memory\n", __func__);
return -ENOMEM;
}
/* Initialize all port interrupt end point to port 0 int
* endpoint. Our device has only one interrupt endpoint
* common to all ports */
serial->port[i]->interrupt_in_endpointAddress =
serial->port[0]->interrupt_in_endpointAddress;
mos7720_port->port = serial->port[i];
usb_set_serial_port_data(serial->port[i], mos7720_port);
dev_dbg(&dev->dev, "port number is %d\n", serial->port[i]->number);
dev_dbg(&dev->dev, "serial number is %d\n", serial->minor);
}
/* setting configuration feature to one */
usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
(__u8)0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5*HZ);
......@@ -2049,8 +2024,6 @@ static int mos7720_startup(struct usb_serial *serial)
static void mos7720_release(struct usb_serial *serial)
{
int i;
#ifdef CONFIG_USB_SERIAL_MOS7715_PARPORT
/* close the parallel port */
......@@ -2089,9 +2062,36 @@ static void mos7720_release(struct usb_serial *serial)
kref_put(&mos_parport->ref_count, destroy_mos_parport);
}
#endif
/* free private structure allocated for serial port */
for (i = 0; i < serial->num_ports; ++i)
kfree(usb_get_serial_port_data(serial->port[i]));
}
static int mos7720_port_probe(struct usb_serial_port *port)
{
struct moschip_port *mos7720_port;
mos7720_port = kzalloc(sizeof(*mos7720_port), GFP_KERNEL);
if (!mos7720_port)
return -ENOMEM;
/* Initialize all port interrupt end point to port 0 int endpoint.
* Our device has only one interrupt endpoint common to all ports.
*/
port->interrupt_in_endpointAddress =
port->serial->port[0]->interrupt_in_endpointAddress;
mos7720_port->port = port;
usb_set_serial_port_data(port, mos7720_port);
return 0;
}
static int mos7720_port_remove(struct usb_serial_port *port)
{
struct moschip_port *mos7720_port;
mos7720_port = usb_get_serial_port_data(port);
kfree(mos7720_port);
return 0;
}
static struct usb_serial_driver moschip7720_2port_driver = {
......@@ -2109,6 +2109,8 @@ static struct usb_serial_driver moschip7720_2port_driver = {
.probe = mos77xx_probe,
.attach = mos7720_startup,
.release = mos7720_release,
.port_probe = mos7720_port_probe,
.port_remove = mos7720_port_remove,
.ioctl = mos7720_ioctl,
.tiocmget = mos7720_tiocmget,
.tiocmset = mos7720_tiocmset,
......
......@@ -218,12 +218,10 @@ struct moschip_port {
int port_num; /*Actual port number in the device(1,2,etc) */
struct urb *write_urb; /* write URB for this port */
struct urb *read_urb; /* read URB for this port */
struct urb *int_urb;
__u8 shadowLCR; /* last LCR value received */
__u8 shadowMCR; /* last MCR value received */
char open;
char open_ports;
char zombie;
wait_queue_head_t wait_chase; /* for handling sleeping while waiting for chase to finish */
wait_queue_head_t delta_msr_wait; /* for handling sleeping while waiting for msr change to happen */
int delta_msr_cond;
......@@ -478,7 +476,6 @@ static void mos7840_control_callback(struct urb *urb)
struct moschip_port *mos7840_port;
struct device *dev = &urb->dev->dev;
__u8 regval = 0x0;
int result = 0;
int status = urb->status;
mos7840_port = urb->context;
......@@ -495,7 +492,7 @@ static void mos7840_control_callback(struct urb *urb)
return;
default:
dev_dbg(dev, "%s - nonzero urb status received: %d\n", __func__, status);
goto exit;
return;
}
dev_dbg(dev, "%s urb buffer size is %d\n", __func__, urb->actual_length);
......@@ -508,16 +505,6 @@ static void mos7840_control_callback(struct urb *urb)
mos7840_handle_new_msr(mos7840_port, regval);
else if (mos7840_port->MsrLsr == 1)
mos7840_handle_new_lsr(mos7840_port, regval);
exit:
spin_lock(&mos7840_port->pool_lock);
if (!mos7840_port->zombie)
result = usb_submit_urb(mos7840_port->int_urb, GFP_ATOMIC);
spin_unlock(&mos7840_port->pool_lock);
if (result) {
dev_err(dev, "%s - Error %d submitting interrupt urb\n",
__func__, result);
}
}
static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg,
......@@ -686,14 +673,7 @@ static void mos7840_interrupt_callback(struct urb *urb)
wreg = MODEM_STATUS_REGISTER;
break;
}
spin_lock(&mos7840_port->pool_lock);
if (!mos7840_port->zombie) {
rv = mos7840_get_reg(mos7840_port, wval, wreg, &Data);
} else {
spin_unlock(&mos7840_port->pool_lock);
return;
}
spin_unlock(&mos7840_port->pool_lock);
}
}
}
......@@ -2347,184 +2327,168 @@ static int mos7840_calc_num_ports(struct usb_serial *serial)
return mos7840_num_ports;
}
/****************************************************************************
* mos7840_startup
****************************************************************************/
static int mos7840_startup(struct usb_serial *serial)
static int mos7840_port_probe(struct usb_serial_port *port)
{
struct usb_serial *serial = port->serial;
struct moschip_port *mos7840_port;
struct usb_device *dev;
int i, status;
int status;
int pnum;
__u16 Data;
dev = serial->dev;
/* we set up the pointers to the endpoints in the mos7840_open *
* function, as the structures aren't created yet. */
/* set up port private structures */
for (i = 0; i < serial->num_ports; ++i) {
dev_dbg(&dev->dev, "mos7840_startup: configuring port %d............\n", i);
pnum = port->number - serial->minor;
dev_dbg(&port->dev, "mos7840_startup: configuring port %d\n", pnum);
mos7840_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL);
if (mos7840_port == NULL) {
dev_err(&dev->dev, "%s - Out of memory\n", __func__);
status = -ENOMEM;
i--; /* don't follow NULL pointer cleaning up */
goto error;
dev_err(&port->dev, "%s - Out of memory\n", __func__);
return -ENOMEM;
}
/* Initialize all port interrupt end point to port 0 int
* endpoint. Our device has only one interrupt end point
* common to all port */
mos7840_port->port = serial->port[i];
mos7840_set_port_private(serial->port[i], mos7840_port);
mos7840_port->port = port;
mos7840_set_port_private(port, mos7840_port);
spin_lock_init(&mos7840_port->pool_lock);
/* minor is not initialised until later by
* usb-serial.c:get_free_serial() and cannot therefore be used
* to index device instances */
mos7840_port->port_num = i + 1;
dev_dbg(&dev->dev, "serial->port[i]->number = %d\n", serial->port[i]->number);
dev_dbg(&dev->dev, "serial->port[i]->serial->minor = %d\n", serial->port[i]->serial->minor);
dev_dbg(&dev->dev, "mos7840_port->port_num = %d\n", mos7840_port->port_num);
dev_dbg(&dev->dev, "serial->minor = %d\n", serial->minor);
mos7840_port->port_num = pnum + 1;
dev_dbg(&port->dev, "port->number = %d\n", port->number);
dev_dbg(&port->dev, "port->serial->minor = %d\n", port->serial->minor);
dev_dbg(&port->dev, "mos7840_port->port_num = %d\n", mos7840_port->port_num);
dev_dbg(&port->dev, "serial->minor = %d\n", serial->minor);
if (mos7840_port->port_num == 1) {
mos7840_port->SpRegOffset = 0x0;
mos7840_port->ControlRegOffset = 0x1;
mos7840_port->DcrRegOffset = 0x4;
} else if ((mos7840_port->port_num == 2)
&& (serial->num_ports == 4)) {
} else if ((mos7840_port->port_num == 2) && (serial->num_ports == 4)) {
mos7840_port->SpRegOffset = 0x8;
mos7840_port->ControlRegOffset = 0x9;
mos7840_port->DcrRegOffset = 0x16;
} else if ((mos7840_port->port_num == 2)
&& (serial->num_ports == 2)) {
} else if ((mos7840_port->port_num == 2) && (serial->num_ports == 2)) {
mos7840_port->SpRegOffset = 0xa;
mos7840_port->ControlRegOffset = 0xb;
mos7840_port->DcrRegOffset = 0x19;
} else if ((mos7840_port->port_num == 3)
&& (serial->num_ports == 4)) {
} else if ((mos7840_port->port_num == 3) && (serial->num_ports == 4)) {
mos7840_port->SpRegOffset = 0xa;
mos7840_port->ControlRegOffset = 0xb;
mos7840_port->DcrRegOffset = 0x19;
} else if ((mos7840_port->port_num == 4)
&& (serial->num_ports == 4)) {
} else if ((mos7840_port->port_num == 4) && (serial->num_ports == 4)) {
mos7840_port->SpRegOffset = 0xc;
mos7840_port->ControlRegOffset = 0xd;
mos7840_port->DcrRegOffset = 0x1c;
}
mos7840_dump_serial_port(serial->port[i], mos7840_port);
mos7840_set_port_private(serial->port[i], mos7840_port);
mos7840_dump_serial_port(port, mos7840_port);
mos7840_set_port_private(port, mos7840_port);
/* enable rx_disable bit in control register */
status = mos7840_get_reg_sync(serial->port[i],
status = mos7840_get_reg_sync(port,
mos7840_port->ControlRegOffset, &Data);
if (status < 0) {
dev_dbg(&dev->dev, "Reading ControlReg failed status-0x%x\n", status);
break;
dev_dbg(&port->dev, "Reading ControlReg failed status-0x%x\n", status);
goto out;
} else
dev_dbg(&dev->dev, "ControlReg Reading success val is %x, status%d\n", Data, status);
dev_dbg(&port->dev, "ControlReg Reading success val is %x, status%d\n", Data, status);
Data |= 0x08; /* setting driver done bit */
Data |= 0x04; /* sp1_bit to have cts change reflect in
modem status reg */
/* Data |= 0x20; //rx_disable bit */
status = mos7840_set_reg_sync(serial->port[i],
status = mos7840_set_reg_sync(port,
mos7840_port->ControlRegOffset, Data);
if (status < 0) {
dev_dbg(&dev->dev, "Writing ControlReg failed(rx_disable) status-0x%x\n", status);
break;
dev_dbg(&port->dev, "Writing ControlReg failed(rx_disable) status-0x%x\n", status);
goto out;
} else
dev_dbg(&dev->dev, "ControlReg Writing success(rx_disable) status%d\n", status);
dev_dbg(&port->dev, "ControlReg Writing success(rx_disable) status%d\n", status);
/* Write default values in DCR (i.e 0x01 in DCR0, 0x05 in DCR2
and 0x24 in DCR3 */
Data = 0x01;
status = mos7840_set_reg_sync(serial->port[i],
status = mos7840_set_reg_sync(port,
(__u16) (mos7840_port->DcrRegOffset + 0), Data);
if (status < 0) {
dev_dbg(&dev->dev, "Writing DCR0 failed status-0x%x\n", status);
break;
dev_dbg(&port->dev, "Writing DCR0 failed status-0x%x\n", status);
goto out;
} else
dev_dbg(&dev->dev, "DCR0 Writing success status%d\n", status);
dev_dbg(&port->dev, "DCR0 Writing success status%d\n", status);
Data = 0x05;
status = mos7840_set_reg_sync(serial->port[i],
status = mos7840_set_reg_sync(port,
(__u16) (mos7840_port->DcrRegOffset + 1), Data);
if (status < 0) {
dev_dbg(&dev->dev, "Writing DCR1 failed status-0x%x\n", status);
break;
dev_dbg(&port->dev, "Writing DCR1 failed status-0x%x\n", status);
goto out;
} else
dev_dbg(&dev->dev, "DCR1 Writing success status%d\n", status);
dev_dbg(&port->dev, "DCR1 Writing success status%d\n", status);
Data = 0x24;
status = mos7840_set_reg_sync(serial->port[i],
status = mos7840_set_reg_sync(port,
(__u16) (mos7840_port->DcrRegOffset + 2), Data);
if (status < 0) {
dev_dbg(&dev->dev, "Writing DCR2 failed status-0x%x\n", status);
break;
dev_dbg(&port->dev, "Writing DCR2 failed status-0x%x\n", status);
goto out;
} else
dev_dbg(&dev->dev, "DCR2 Writing success status%d\n", status);
dev_dbg(&port->dev, "DCR2 Writing success status%d\n", status);
/* write values in clkstart0x0 and clkmulti 0x20 */
Data = 0x0;
status = mos7840_set_reg_sync(serial->port[i],
CLK_START_VALUE_REGISTER, Data);
status = mos7840_set_reg_sync(port, CLK_START_VALUE_REGISTER, Data);
if (status < 0) {
dev_dbg(&dev->dev, "Writing CLK_START_VALUE_REGISTER failed status-0x%x\n", status);
break;
dev_dbg(&port->dev, "Writing CLK_START_VALUE_REGISTER failed status-0x%x\n", status);
goto out;
} else
dev_dbg(&dev->dev, "CLK_START_VALUE_REGISTER Writing success status%d\n", status);
dev_dbg(&port->dev, "CLK_START_VALUE_REGISTER Writing success status%d\n", status);
Data = 0x20;
status = mos7840_set_reg_sync(serial->port[i],
CLK_MULTI_REGISTER, Data);
status = mos7840_set_reg_sync(port, CLK_MULTI_REGISTER, Data);
if (status < 0) {
dev_dbg(&dev->dev, "Writing CLK_MULTI_REGISTER failed status-0x%x\n", status);
dev_dbg(&port->dev, "Writing CLK_MULTI_REGISTER failed status-0x%x\n", status);
goto error;
} else
dev_dbg(&dev->dev, "CLK_MULTI_REGISTER Writing success status%d\n", status);
dev_dbg(&port->dev, "CLK_MULTI_REGISTER Writing success status%d\n", status);
/* write value 0x0 to scratchpad register */
Data = 0x00;
status = mos7840_set_uart_reg(serial->port[i],
SCRATCH_PAD_REGISTER, Data);
status = mos7840_set_uart_reg(port, SCRATCH_PAD_REGISTER, Data);
if (status < 0) {
dev_dbg(&dev->dev, "Writing SCRATCH_PAD_REGISTER failed status-0x%x\n", status);
break;
dev_dbg(&port->dev, "Writing SCRATCH_PAD_REGISTER failed status-0x%x\n", status);
goto out;
} else
dev_dbg(&dev->dev, "SCRATCH_PAD_REGISTER Writing success status%d\n", status);
dev_dbg(&port->dev, "SCRATCH_PAD_REGISTER Writing success status%d\n", status);
/* Zero Length flag register */
if ((mos7840_port->port_num != 1)
&& (serial->num_ports == 2)) {
if ((mos7840_port->port_num != 1) && (serial->num_ports == 2)) {
Data = 0xff;
status = mos7840_set_reg_sync(serial->port[i],
status = mos7840_set_reg_sync(port,
(__u16) (ZLP_REG1 +
((__u16)mos7840_port->port_num)), Data);
dev_dbg(&dev->dev, "ZLIP offset %x\n",
dev_dbg(&port->dev, "ZLIP offset %x\n",
(__u16)(ZLP_REG1 + ((__u16) mos7840_port->port_num)));
if (status < 0) {
dev_dbg(&dev->dev, "Writing ZLP_REG%d failed status-0x%x\n", i + 2, status);
break;
dev_dbg(&port->dev, "Writing ZLP_REG%d failed status-0x%x\n", pnum + 2, status);
goto out;
} else
dev_dbg(&dev->dev, "ZLP_REG%d Writing success status%d\n", i + 2, status);
dev_dbg(&port->dev, "ZLP_REG%d Writing success status%d\n", pnum + 2, status);
} else {
Data = 0xff;
status = mos7840_set_reg_sync(serial->port[i],
status = mos7840_set_reg_sync(port,
(__u16) (ZLP_REG1 +
((__u16)mos7840_port->port_num) - 0x1), Data);
dev_dbg(&dev->dev, "ZLIP offset %x\n",
dev_dbg(&port->dev, "ZLIP offset %x\n",
(__u16)(ZLP_REG1 + ((__u16) mos7840_port->port_num) - 0x1));
if (status < 0) {
dev_dbg(&dev->dev, "Writing ZLP_REG%d failed status-0x%x\n", i + 1, status);
break;
dev_dbg(&port->dev, "Writing ZLP_REG%d failed status-0x%x\n", pnum + 1, status);
goto out;
} else
dev_dbg(&dev->dev, "ZLP_REG%d Writing success status%d\n", i + 1, status);
dev_dbg(&port->dev, "ZLP_REG%d Writing success status%d\n", pnum + 1, status);
}
mos7840_port->control_urb = usb_alloc_urb(0, GFP_KERNEL);
......@@ -2547,109 +2511,65 @@ static int mos7840_startup(struct usb_serial *serial)
mos7840_port->led_timer1.function = mos7840_led_off;
mos7840_port->led_timer1.expires =
jiffies + msecs_to_jiffies(LED_ON_MS);
mos7840_port->led_timer1.data =
(unsigned long)mos7840_port;
mos7840_port->led_timer1.data = (unsigned long)mos7840_port;
init_timer(&mos7840_port->led_timer2);
mos7840_port->led_timer2.function =
mos7840_led_flag_off;
mos7840_port->led_timer2.function = mos7840_led_flag_off;
mos7840_port->led_timer2.expires =
jiffies + msecs_to_jiffies(LED_OFF_MS);
mos7840_port->led_timer2.data =
(unsigned long)mos7840_port;
mos7840_port->led_timer2.data = (unsigned long)mos7840_port;
mos7840_port->led_flag = false;
/* Turn off LED */
mos7840_set_led_sync(serial->port[i],
MODEM_CONTROL_REGISTER, 0x0300);
}
mos7840_set_led_sync(port, MODEM_CONTROL_REGISTER, 0x0300);
}
out:
if (pnum == serial->num_ports - 1) {
/* Zero Length flag enable */
Data = 0x0f;
status = mos7840_set_reg_sync(serial->port[0], ZLP_REG5, Data);
if (status < 0) {
dev_dbg(&dev->dev, "Writing ZLP_REG5 failed status-0x%x\n", status);
dev_dbg(&port->dev, "Writing ZLP_REG5 failed status-0x%x\n", status);
goto error;
} else
dev_dbg(&dev->dev, "ZLP_REG5 Writing success status%d\n", status);
dev_dbg(&port->dev, "ZLP_REG5 Writing success status%d\n", status);
/* setting configuration feature to one */
usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
(__u8) 0x03, 0x00, 0x01, 0x00, NULL, 0x00, MOS_WDR_TIMEOUT);
0x03, 0x00, 0x01, 0x00, NULL, 0x00,
MOS_WDR_TIMEOUT);
}
return 0;
error:
for (/* nothing */; i >= 0; i--) {
mos7840_port = mos7840_get_port_private(serial->port[i]);
kfree(mos7840_port->dr);
kfree(mos7840_port->ctrl_buf);
usb_free_urb(mos7840_port->control_urb);
kfree(mos7840_port);
serial->port[i] = NULL;
}
return status;
}
/****************************************************************************
* mos7840_disconnect
* This function is called whenever the device is removed from the usb bus.
****************************************************************************/
static void mos7840_disconnect(struct usb_serial *serial)
{
int i;
unsigned long flags;
struct moschip_port *mos7840_port;
/* check for the ports to be closed,close the ports and disconnect */
/* free private structure allocated for serial port *
* stop reads and writes on all ports */
for (i = 0; i < serial->num_ports; ++i) {
mos7840_port = mos7840_get_port_private(serial->port[i]);
if (mos7840_port) {
spin_lock_irqsave(&mos7840_port->pool_lock, flags);
mos7840_port->zombie = 1;
spin_unlock_irqrestore(&mos7840_port->pool_lock, flags);
usb_kill_urb(mos7840_port->control_urb);
}
}
return status;
}
/****************************************************************************
* mos7840_release
* This function is called when the usb_serial structure is freed.
****************************************************************************/
static void mos7840_release(struct usb_serial *serial)
static int mos7840_port_remove(struct usb_serial_port *port)
{
int i;
struct moschip_port *mos7840_port;
/* check for the ports to be closed,close the ports and disconnect */
/* free private structure allocated for serial port *
* stop reads and writes on all ports */
mos7840_port = mos7840_get_port_private(port);
for (i = 0; i < serial->num_ports; ++i) {
mos7840_port = mos7840_get_port_private(serial->port[i]);
if (mos7840_port) {
if (mos7840_port->has_led) {
/* Turn off LED */
mos7840_set_led_sync(mos7840_port->port,
MODEM_CONTROL_REGISTER, 0x0300);
mos7840_set_led_sync(port, MODEM_CONTROL_REGISTER, 0x0300);
del_timer_sync(&mos7840_port->led_timer1);
del_timer_sync(&mos7840_port->led_timer2);
}
usb_kill_urb(mos7840_port->control_urb);
usb_free_urb(mos7840_port->control_urb);
kfree(mos7840_port->ctrl_buf);
kfree(mos7840_port->dr);
kfree(mos7840_port);
}
}
return 0;
}
static struct usb_serial_driver moschip7840_4port_device = {
......@@ -2677,9 +2597,8 @@ static struct usb_serial_driver moschip7840_4port_device = {
.tiocmget = mos7840_tiocmget,
.tiocmset = mos7840_tiocmset,
.get_icount = mos7840_get_icount,
.attach = mos7840_startup,
.disconnect = mos7840_disconnect,
.release = mos7840_release,
.port_probe = mos7840_port_probe,
.port_remove = mos7840_port_remove,
.read_bulk_callback = mos7840_bulk_in_callback,
.read_int_callback = mos7840_interrupt_callback,
};
......
......@@ -44,8 +44,8 @@ static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port,
const unsigned char *buf, int count);
static int omninet_write_room(struct tty_struct *tty);
static void omninet_disconnect(struct usb_serial *serial);
static void omninet_release(struct usb_serial *serial);
static int omninet_attach(struct usb_serial *serial);
static int omninet_port_probe(struct usb_serial_port *port);
static int omninet_port_remove(struct usb_serial_port *port);
static const struct usb_device_id id_table[] = {
{ USB_DEVICE(ZYXEL_VENDOR_ID, ZYXEL_OMNINET_ID) },
......@@ -62,7 +62,8 @@ static struct usb_serial_driver zyxel_omninet_device = {
.description = "ZyXEL - omni.net lcd plus usb",
.id_table = id_table,
.num_ports = 1,
.attach = omninet_attach,
.port_probe = omninet_port_probe,
.port_remove = omninet_port_remove,
.open = omninet_open,
.close = omninet_close,
.write = omninet_write,
......@@ -70,7 +71,6 @@ static struct usb_serial_driver zyxel_omninet_device = {
.read_bulk_callback = omninet_read_bulk_callback,
.write_bulk_callback = omninet_write_bulk_callback,
.disconnect = omninet_disconnect,
.release = omninet_release,
};
static struct usb_serial_driver * const serial_drivers[] = {
......@@ -112,18 +112,26 @@ struct omninet_data {
__u8 od_outseq; /* Sequence number for bulk_out URBs */
};
static int omninet_attach(struct usb_serial *serial)
static int omninet_port_probe(struct usb_serial_port *port)
{
struct omninet_data *od;
struct usb_serial_port *port = serial->port[0];
od = kmalloc(sizeof(struct omninet_data), GFP_KERNEL);
if (!od) {
dev_err(&port->dev, "%s- kmalloc(%Zd) failed.\n",
__func__, sizeof(struct omninet_data));
if (!od)
return -ENOMEM;
}
usb_set_serial_port_data(port, od);
return 0;
}
static int omninet_port_remove(struct usb_serial_port *port)
{
struct omninet_data *od;
od = usb_get_serial_port_data(port);
kfree(od);
return 0;
}
......@@ -279,14 +287,6 @@ static void omninet_disconnect(struct usb_serial *serial)
usb_kill_urb(wport->write_urb);
}
static void omninet_release(struct usb_serial *serial)
{
struct usb_serial_port *port = serial->port[0];
kfree(usb_get_serial_port_data(port));
}
module_usb_serial_driver(serial_drivers, id_table);
MODULE_AUTHOR(DRIVER_AUTHOR);
......
......@@ -155,7 +155,11 @@ static int send_control_msg(struct usb_serial_port *port, u8 requesttype,
{
struct usb_serial *serial = port->serial;
int retval;
u8 buffer[2];
u8 *buffer;
buffer = kzalloc(1, GFP_KERNEL);
if (!buffer)
return -ENOMEM;
buffer[0] = val;
/* Send the message to the vendor control endpoint
......@@ -164,6 +168,7 @@ static int send_control_msg(struct usb_serial_port *port, u8 requesttype,
requesttype,
USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE,
0, 0, buffer, 1, 0);
kfree(buffer);
return retval;
}
......@@ -281,7 +286,7 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port,
if (!dr) {
dev_err(&port->dev, "out of memory\n");
count = -ENOMEM;
goto error;
goto error_no_dr;
}
dr->bRequestType = USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT;
......@@ -311,6 +316,8 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port,
return count;
error:
kfree(dr);
error_no_dr:
usb_free_urb(urb);
error_no_urb:
kfree(buffer);
......
......@@ -47,6 +47,7 @@
/* Function prototypes */
static int option_probe(struct usb_serial *serial,
const struct usb_device_id *id);
static int option_attach(struct usb_serial *serial);
static void option_release(struct usb_serial *serial);
static int option_send_setup(struct usb_serial_port *port);
static void option_instat_callback(struct urb *urb);
......@@ -1288,8 +1289,9 @@ static struct usb_serial_driver option_1port_device = {
.tiocmget = usb_wwan_tiocmget,
.tiocmset = usb_wwan_tiocmset,
.ioctl = usb_wwan_ioctl,
.attach = usb_wwan_startup,
.attach = option_attach,
.release = option_release,
.port_probe = usb_wwan_port_probe,
.port_remove = usb_wwan_port_remove,
.read_int_callback = option_instat_callback,
#ifdef CONFIG_PM
......@@ -1335,8 +1337,6 @@ static bool is_blacklisted(const u8 ifnum, enum option_blacklist_reason reason,
static int option_probe(struct usb_serial *serial,
const struct usb_device_id *id)
{
struct usb_wwan_intf_private *data;
struct option_private *priv;
struct usb_interface_descriptor *iface_desc =
&serial->interface->cur_altsetting->desc;
struct usb_device_descriptor *dev_desc = &serial->dev->descriptor;
......@@ -1374,6 +1374,19 @@ static int option_probe(struct usb_serial *serial,
iface_desc->bInterfaceClass != USB_CLASS_CDC_DATA)
return -ENODEV;
/* Store device id so we can use it during attach. */
usb_set_serial_data(serial, (void *)id);
return 0;
}
static int option_attach(struct usb_serial *serial)
{
struct usb_interface_descriptor *iface_desc;
const struct usb_device_id *id;
struct usb_wwan_intf_private *data;
struct option_private *priv;
data = kzalloc(sizeof(struct usb_wwan_intf_private), GFP_KERNEL);
if (!data)
return -ENOMEM;
......@@ -1384,6 +1397,10 @@ static int option_probe(struct usb_serial *serial,
return -ENOMEM;
}
/* Retrieve device id stored at probe. */
id = usb_get_serial_data(serial);
iface_desc = &serial->interface->cur_altsetting->desc;
priv->bInterfaceNumber = iface_desc->bInterfaceNumber;
data->private = priv;
......
......@@ -138,7 +138,6 @@ MODULE_DEVICE_TABLE(usb, id_table);
static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
{
struct usb_wwan_intf_private *data;
struct usb_host_interface *intf = serial->interface->cur_altsetting;
struct device *dev = &serial->dev->dev;
int retval = -ENODEV;
......@@ -154,13 +153,6 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
ifnum = intf->desc.bInterfaceNumber;
dev_dbg(dev, "This Interface = %d\n", ifnum);
data = kzalloc(sizeof(struct usb_wwan_intf_private),
GFP_KERNEL);
if (!data)
return -ENOMEM;
spin_lock_init(&data->susp_lock);
if (nintf == 1) {
/* QDL mode */
/* Gobi 2000 has a single altsetting, older ones have two */
......@@ -253,20 +245,28 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
}
}
/* Set serial->private if not returning error */
if (retval == 0)
return retval;
}
static int qc_attach(struct usb_serial *serial)
{
struct usb_wwan_intf_private *data;
data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
spin_lock_init(&data->susp_lock);
usb_set_serial_data(serial, data);
else
kfree(data);
return retval;
return 0;
}
static void qc_release(struct usb_serial *serial)
{
struct usb_wwan_intf_private *priv = usb_get_serial_data(serial);
/* Free the private data allocated in qcprobe */
usb_set_serial_data(serial, NULL);
kfree(priv);
}
......@@ -285,8 +285,9 @@ static struct usb_serial_driver qcdevice = {
.write = usb_wwan_write,
.write_room = usb_wwan_write_room,
.chars_in_buffer = usb_wwan_chars_in_buffer,
.attach = usb_wwan_startup,
.attach = qc_attach,
.release = qc_release,
.port_probe = usb_wwan_port_probe,
.port_remove = usb_wwan_port_remove,
#ifdef CONFIG_PM
.suspend = usb_wwan_suspend,
......
......@@ -143,12 +143,12 @@ static void qt2_read_bulk_callback(struct urb *urb);
static void qt2_release(struct usb_serial *serial)
{
int i;
struct qt2_serial_private *serial_priv;
kfree(usb_get_serial_data(serial));
serial_priv = usb_get_serial_data(serial);
for (i = 0; i < serial->num_ports; i++)
kfree(usb_get_serial_port_data(serial->port[i]));
usb_free_urb(serial_priv->read_urb);
kfree(serial_priv);
}
static inline int calc_baud_divisor(int baudrate)
......@@ -423,11 +423,16 @@ static void qt2_close(struct usb_serial_port *port)
port_priv->is_open = false;
spin_lock_irqsave(&port_priv->urb_lock, flags);
if (port_priv->write_urb->status == -EINPROGRESS)
usb_kill_urb(port_priv->write_urb);
port_priv->urb_in_use = false;
spin_unlock_irqrestore(&port_priv->urb_lock, flags);
mutex_lock(&port->serial->disc_mutex);
if (port->serial->disconnected) {
mutex_unlock(&port->serial->disc_mutex);
return;
}
/* flush the port transmit buffer */
i = usb_control_msg(serial->dev,
usb_rcvctrlpipe(serial->dev, 0),
......@@ -459,26 +464,14 @@ static void qt2_close(struct usb_serial_port *port)
dev_err(&port->dev, "%s - close port failed %i\n",
__func__, i);
mutex_unlock(&port->serial->disc_mutex);
}
static void qt2_disconnect(struct usb_serial *serial)
{
struct qt2_serial_private *serial_priv = usb_get_serial_data(serial);
struct qt2_port_private *port_priv;
int i;
if (serial_priv->read_urb->status == -EINPROGRESS)
usb_kill_urb(serial_priv->read_urb);
usb_free_urb(serial_priv->read_urb);
for (i = 0; i < serial->num_ports; i++) {
port_priv = usb_get_serial_port_data(serial->port[i]);
if (port_priv->write_urb->status == -EINPROGRESS)
usb_kill_urb(port_priv->write_urb);
usb_free_urb(port_priv->write_urb);
}
}
static int get_serial_info(struct usb_serial_port *port,
......@@ -773,11 +766,9 @@ static void qt2_read_bulk_callback(struct urb *urb)
static int qt2_setup_urbs(struct usb_serial *serial)
{
struct usb_serial_port *port;
struct usb_serial_port *port0;
struct qt2_serial_private *serial_priv;
struct qt2_port_private *port_priv;
int pcount, status;
int status;
port0 = serial->port[0];
......@@ -795,46 +786,21 @@ static int qt2_setup_urbs(struct usb_serial *serial)
sizeof(serial_priv->read_buffer),
qt2_read_bulk_callback, serial);
/* setup write_urb for each port */
for (pcount = 0; pcount < serial->num_ports; pcount++) {
port = serial->port[pcount];
port_priv = usb_get_serial_port_data(port);
port_priv->write_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!port_priv->write_urb) {
dev_err(&serial->dev->dev,
"failed to alloc write_urb for port %i\n",
pcount);
return -ENOMEM;
}
usb_fill_bulk_urb(port_priv->write_urb,
serial->dev,
usb_sndbulkpipe(serial->dev,
port0->
bulk_out_endpointAddress),
port_priv->write_buffer,
sizeof(port_priv->write_buffer),
qt2_write_bulk_callback, port);
}
status = usb_submit_urb(serial_priv->read_urb, GFP_KERNEL);
if (status != 0) {
dev_err(&serial->dev->dev,
"%s - submit read urb failed %i\n", __func__, status);
usb_free_urb(serial_priv->read_urb);
return status;
}
return 0;
}
static int qt2_attach(struct usb_serial *serial)
{
struct qt2_serial_private *serial_priv;
struct qt2_port_private *port_priv;
int status, pcount;
int status;
/* power on unit */
status = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
......@@ -854,39 +820,58 @@ static int qt2_attach(struct usb_serial *serial)
usb_set_serial_data(serial, serial_priv);
for (pcount = 0; pcount < serial->num_ports; pcount++) {
port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL);
if (!port_priv) {
dev_err(&serial->dev->dev,
"%s- kmalloc(%Zd) failed.\n", __func__,
sizeof(*port_priv));
pcount--;
status = -ENOMEM;
status = qt2_setup_urbs(serial);
if (status != 0)
goto attach_failed;
}
return 0;
attach_failed:
kfree(serial_priv);
return status;
}
static int qt2_port_probe(struct usb_serial_port *port)
{
struct usb_serial *serial = port->serial;
struct qt2_port_private *port_priv;
u8 bEndpointAddress;
port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL);
if (!port_priv)
return -ENOMEM;
spin_lock_init(&port_priv->lock);
spin_lock_init(&port_priv->urb_lock);
init_waitqueue_head(&port_priv->delta_msr_wait);
port_priv->port = port;
port_priv->port = serial->port[pcount];
usb_set_serial_port_data(serial->port[pcount], port_priv);
port_priv->write_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!port_priv->write_urb) {
kfree(port_priv);
return -ENOMEM;
}
bEndpointAddress = serial->port[0]->bulk_out_endpointAddress;
usb_fill_bulk_urb(port_priv->write_urb, serial->dev,
usb_sndbulkpipe(serial->dev, bEndpointAddress),
port_priv->write_buffer,
sizeof(port_priv->write_buffer),
qt2_write_bulk_callback, port);
status = qt2_setup_urbs(serial);
if (status != 0)
goto attach_failed;
usb_set_serial_port_data(port, port_priv);
return 0;
}
attach_failed:
for (/* empty */; pcount >= 0; pcount--) {
port_priv = usb_get_serial_port_data(serial->port[pcount]);
static int qt2_port_remove(struct usb_serial_port *port)
{
struct qt2_port_private *port_priv;
port_priv = usb_get_serial_port_data(port);
usb_free_urb(port_priv->write_urb);
kfree(port_priv);
}
kfree(serial_priv);
return status;
return 0;
}
static int qt2_tiocmget(struct tty_struct *tty)
......@@ -1127,6 +1112,8 @@ static struct usb_serial_driver qt2_device = {
.attach = qt2_attach,
.release = qt2_release,
.disconnect = qt2_disconnect,
.port_probe = qt2_port_probe,
.port_remove = qt2_port_remove,
.dtr_rts = qt2_dtr_rts,
.break_ctl = qt2_break_ctl,
.tiocmget = qt2_tiocmget,
......
......@@ -161,7 +161,6 @@ static int sierra_probe(struct usb_serial *serial,
{
int result = 0;
struct usb_device *udev;
struct sierra_intf_private *data;
u8 ifnum;
udev = serial->dev;
......@@ -188,11 +187,6 @@ static int sierra_probe(struct usb_serial *serial,
return -ENODEV;
}
data = serial->private = kzalloc(sizeof(struct sierra_intf_private), GFP_KERNEL);
if (!data)
return -ENOMEM;
spin_lock_init(&data->susp_lock);
return result;
}
......@@ -884,11 +878,15 @@ static void sierra_dtr_rts(struct usb_serial_port *port, int on)
static int sierra_startup(struct usb_serial *serial)
{
struct usb_serial_port *port;
struct sierra_port_private *portdata;
struct sierra_iface_info *himemoryp = NULL;
int i;
u8 ifnum;
struct sierra_intf_private *intfdata;
intfdata = kzalloc(sizeof(*intfdata), GFP_KERNEL);
if (!intfdata)
return -ENOMEM;
spin_lock_init(&intfdata->susp_lock);
usb_set_serial_data(serial, intfdata);
/* Set Device mode to D0 */
sierra_set_power_state(serial->dev, 0x0000);
......@@ -897,20 +895,32 @@ static int sierra_startup(struct usb_serial *serial)
if (nmea)
sierra_vsc_set_nmea(serial->dev, 1);
/* Now setup per port private data */
for (i = 0; i < serial->num_ports; i++) {
port = serial->port[i];
return 0;
}
static void sierra_release(struct usb_serial *serial)
{
struct sierra_intf_private *intfdata;
intfdata = usb_get_serial_data(serial);
kfree(intfdata);
}
static int sierra_port_probe(struct usb_serial_port *port)
{
struct usb_serial *serial = port->serial;
struct sierra_port_private *portdata;
const struct sierra_iface_info *himemoryp;
u8 ifnum;
portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
if (!portdata) {
dev_dbg(&port->dev, "%s: kmalloc for "
"sierra_port_private (%d) failed!\n",
__func__, i);
if (!portdata)
return -ENOMEM;
}
spin_lock_init(&portdata->lock);
init_usb_anchor(&portdata->active);
init_usb_anchor(&portdata->delayed);
ifnum = i;
/* Assume low memory requirements */
portdata->num_out_urbs = N_OUT_URB;
portdata->num_in_urbs = N_IN_URB;
......@@ -919,46 +929,37 @@ static int sierra_startup(struct usb_serial *serial)
if (serial->num_ports == 1) {
/* Get interface number for composite device */
ifnum = sierra_calc_interface(serial);
himemoryp =
(struct sierra_iface_info *)&typeB_interface_list;
if (is_himemory(ifnum, himemoryp)) {
portdata->num_out_urbs = N_OUT_URB_HM;
portdata->num_in_urbs = N_IN_URB_HM;
}
himemoryp = &typeB_interface_list;
} else {
/* This is really the usb-serial port number of the interface
* rather than the interface number.
*/
ifnum = port->number - serial->minor;
himemoryp = &typeA_interface_list;
}
else {
himemoryp =
(struct sierra_iface_info *)&typeA_interface_list;
if (is_himemory(i, himemoryp)) {
if (is_himemory(ifnum, himemoryp)) {
portdata->num_out_urbs = N_OUT_URB_HM;
portdata->num_in_urbs = N_IN_URB_HM;
}
}
dev_dbg(&serial->dev->dev,
dev_dbg(&port->dev,
"Memory usage (urbs) interface #%d, in=%d, out=%d\n",
ifnum,portdata->num_in_urbs, portdata->num_out_urbs );
/* Set the port private data pointer */
ifnum, portdata->num_in_urbs, portdata->num_out_urbs);
usb_set_serial_port_data(port, portdata);
}
return 0;
}
static void sierra_release(struct usb_serial *serial)
static int sierra_port_remove(struct usb_serial_port *port)
{
int i;
struct usb_serial_port *port;
struct sierra_port_private *portdata;
for (i = 0; i < serial->num_ports; ++i) {
port = serial->port[i];
if (!port)
continue;
portdata = usb_get_serial_port_data(port);
if (!portdata)
continue;
kfree(portdata);
}
return 0;
}
#ifdef CONFIG_PM
......@@ -1062,6 +1063,8 @@ static struct usb_serial_driver sierra_device = {
.tiocmset = sierra_tiocmset,
.attach = sierra_startup,
.release = sierra_release,
.port_probe = sierra_port_probe,
.port_remove = sierra_port_remove,
.suspend = sierra_suspend,
.resume = sierra_resume,
.read_int_callback = sierra_instat_callback,
......
......@@ -8,7 +8,7 @@
extern void usb_wwan_dtr_rts(struct usb_serial_port *port, int on);
extern int usb_wwan_open(struct tty_struct *tty, struct usb_serial_port *port);
extern void usb_wwan_close(struct usb_serial_port *port);
extern int usb_wwan_startup(struct usb_serial *serial);
extern int usb_wwan_port_probe(struct usb_serial_port *port);
extern int usb_wwan_port_remove(struct usb_serial_port *port);
extern int usb_wwan_write_room(struct tty_struct *tty);
extern void usb_wwan_set_termios(struct tty_struct *tty,
......
......@@ -447,10 +447,12 @@ void usb_wwan_close(struct usb_serial_port *port)
EXPORT_SYMBOL(usb_wwan_close);
/* Helper functions used by usb_wwan_setup_urbs */
static struct urb *usb_wwan_setup_urb(struct usb_serial *serial, int endpoint,
static struct urb *usb_wwan_setup_urb(struct usb_serial_port *port,
int endpoint,
int dir, void *ctx, char *buf, int len,
void (*callback) (struct urb *))
{
struct usb_serial *serial = port->serial;
struct urb *urb;
if (endpoint == -1)
......@@ -472,101 +474,75 @@ static struct urb *usb_wwan_setup_urb(struct usb_serial *serial, int endpoint,
return urb;
}
/* Setup urbs */
static void usb_wwan_setup_urbs(struct usb_serial *serial)
int usb_wwan_port_probe(struct usb_serial_port *port)
{
int i, j;
struct usb_serial_port *port;
struct usb_wwan_port_private *portdata;
for (i = 0; i < serial->num_ports; i++) {
port = serial->port[i];
portdata = usb_get_serial_port_data(port);
/* Do indat endpoints first */
for (j = 0; j < N_IN_URB; ++j) {
portdata->in_urbs[j] = usb_wwan_setup_urb(serial,
port->
bulk_in_endpointAddress,
USB_DIR_IN,
port,
portdata->
in_buffer[j],
IN_BUFLEN,
usb_wwan_indat_callback);
}
/* outdat endpoints */
for (j = 0; j < N_OUT_URB; ++j) {
portdata->out_urbs[j] = usb_wwan_setup_urb(serial,
port->
bulk_out_endpointAddress,
USB_DIR_OUT,
port,
portdata->
out_buffer
[j],
OUT_BUFLEN,
usb_wwan_outdat_callback);
}
}
}
int usb_wwan_startup(struct usb_serial *serial)
{
int i, j, err;
struct usb_serial_port *port;
struct usb_wwan_port_private *portdata;
struct urb *urb;
u8 *buffer;
int err;
int i;
/* Now setup per port private data */
for (i = 0; i < serial->num_ports; i++) {
port = serial->port[i];
portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
if (!portdata) {
dev_dbg(&port->dev, "%s: kmalloc for usb_wwan_port_private (%d) failed!.\n",
__func__, i);
return 1;
}
if (!portdata)
return -ENOMEM;
init_usb_anchor(&portdata->delayed);
for (j = 0; j < N_IN_URB; j++) {
buffer = (u8 *) __get_free_page(GFP_KERNEL);
for (i = 0; i < N_IN_URB; i++) {
buffer = (u8 *)__get_free_page(GFP_KERNEL);
if (!buffer)
goto bail_out_error;
portdata->in_buffer[j] = buffer;
portdata->in_buffer[i] = buffer;
urb = usb_wwan_setup_urb(port, port->bulk_in_endpointAddress,
USB_DIR_IN, port,
buffer, IN_BUFLEN,
usb_wwan_indat_callback);
portdata->in_urbs[i] = urb;
}
for (j = 0; j < N_OUT_URB; j++) {
for (i = 0; i < N_OUT_URB; i++) {
if (port->bulk_out_endpointAddress == -1)
continue;
buffer = kmalloc(OUT_BUFLEN, GFP_KERNEL);
if (!buffer)
goto bail_out_error2;
portdata->out_buffer[j] = buffer;
portdata->out_buffer[i] = buffer;
urb = usb_wwan_setup_urb(port, port->bulk_out_endpointAddress,
USB_DIR_OUT, port,
buffer, OUT_BUFLEN,
usb_wwan_outdat_callback);
portdata->out_urbs[i] = urb;
}
usb_set_serial_port_data(port, portdata);
if (!port->interrupt_in_urb)
continue;
if (port->interrupt_in_urb) {
err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
if (err)
dev_dbg(&port->dev, "%s: submit irq_in urb failed %d\n",
__func__, err);
}
usb_wwan_setup_urbs(serial);
return 0;
bail_out_error2:
for (j = 0; j < N_OUT_URB; j++)
kfree(portdata->out_buffer[j]);
for (i = 0; i < N_OUT_URB; i++) {
usb_free_urb(portdata->out_urbs[i]);
kfree(portdata->out_buffer[i]);
}
bail_out_error:
for (j = 0; j < N_IN_URB; j++)
if (portdata->in_buffer[j])
free_page((unsigned long)portdata->in_buffer[j]);
for (i = 0; i < N_IN_URB; i++) {
usb_free_urb(portdata->in_urbs[i]);
free_page((unsigned long)portdata->in_buffer[i]);
}
kfree(portdata);
return 1;
return -ENOMEM;
}
EXPORT_SYMBOL(usb_wwan_startup);
EXPORT_SYMBOL_GPL(usb_wwan_port_probe);
int usb_wwan_port_remove(struct usb_serial_port *port)
{
......
......@@ -83,6 +83,8 @@ static int whiteheat_firmware_attach(struct usb_serial *serial);
/* function prototypes for the Connect Tech WhiteHEAT serial converter */
static int whiteheat_attach(struct usb_serial *serial);
static void whiteheat_release(struct usb_serial *serial);
static int whiteheat_port_probe(struct usb_serial_port *port);
static int whiteheat_port_remove(struct usb_serial_port *port);
static int whiteheat_open(struct tty_struct *tty,
struct usb_serial_port *port);
static void whiteheat_close(struct usb_serial_port *port);
......@@ -117,6 +119,8 @@ static struct usb_serial_driver whiteheat_device = {
.num_ports = 4,
.attach = whiteheat_attach,
.release = whiteheat_release,
.port_probe = whiteheat_port_probe,
.port_remove = whiteheat_port_remove,
.open = whiteheat_open,
.close = whiteheat_close,
.ioctl = whiteheat_ioctl,
......@@ -218,15 +222,12 @@ static int whiteheat_attach(struct usb_serial *serial)
{
struct usb_serial_port *command_port;
struct whiteheat_command_private *command_info;
struct usb_serial_port *port;
struct whiteheat_private *info;
struct whiteheat_hw_info *hw_info;
int pipe;
int ret;
int alen;
__u8 *command;
__u8 *result;
int i;
command_port = serial->port[COMMAND_PORT];
......@@ -285,22 +286,6 @@ static int whiteheat_attach(struct usb_serial *serial)
serial->type->description,
hw_info->sw_major_rev, hw_info->sw_minor_rev);
for (i = 0; i < serial->num_ports; i++) {
port = serial->port[i];
info = kmalloc(sizeof(struct whiteheat_private), GFP_KERNEL);
if (info == NULL) {
dev_err(&port->dev,
"%s: Out of memory for port structures\n",
serial->type->description);
goto no_private;
}
info->mcr = 0;
usb_set_serial_port_data(port, info);
}
command_info = kmalloc(sizeof(struct whiteheat_command_private),
GFP_KERNEL);
if (command_info == NULL) {
......@@ -333,16 +318,10 @@ static int whiteheat_attach(struct usb_serial *serial)
"%s: please contact support@connecttech.com\n",
serial->type->description);
kfree(result);
kfree(command);
return -ENODEV;
no_command_private:
for (i = serial->num_ports - 1; i >= 0; i--) {
port = serial->port[i];
info = usb_get_serial_port_data(port);
kfree(info);
no_private:
;
}
kfree(result);
no_result_buffer:
kfree(command);
......@@ -350,21 +329,36 @@ static int whiteheat_attach(struct usb_serial *serial)
return -ENOMEM;
}
static void whiteheat_release(struct usb_serial *serial)
{
struct usb_serial_port *command_port;
struct whiteheat_private *info;
int i;
/* free up our private data for our command port */
command_port = serial->port[COMMAND_PORT];
kfree(usb_get_serial_port_data(command_port));
}
for (i = 0; i < serial->num_ports; i++) {
info = usb_get_serial_port_data(serial->port[i]);
static int whiteheat_port_probe(struct usb_serial_port *port)
{
struct whiteheat_private *info;
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
usb_set_serial_port_data(port, info);
return 0;
}
static int whiteheat_port_remove(struct usb_serial_port *port)
{
struct whiteheat_private *info;
info = usb_get_serial_port_data(port);
kfree(info);
}
return 0;
}
static int whiteheat_open(struct tty_struct *tty, struct usb_serial_port *port)
......
......@@ -1004,6 +1004,12 @@ UNUSUAL_DEV( 0x07cf, 0x1001, 0x1000, 0x9999,
USB_SC_8070, USB_PR_CB, NULL,
US_FL_NEED_OVERRIDE | US_FL_FIX_INQUIRY ),
/* Submitted by Oleksandr Chumachenko <ledest@gmail.com> */
UNUSUAL_DEV( 0x07cf, 0x1167, 0x0100, 0x0100,
"Casio",
"EX-N1 DigitalCamera",
USB_SC_8070, USB_PR_DEVICE, NULL, 0),
/* Submitted by Hartmut Wahl <hwahl@hwahl.de>*/
UNUSUAL_DEV( 0x0839, 0x000a, 0x0001, 0x0001,
"Samsung",
......
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