static int acm_port_activate(struct tty_port *port, struct tty_struct *tty) { struct acm *acm = container_of(port, struct acm, port); int retval = -ENODEV; dev_dbg(&acm->control->dev, "%s\n", __func__); mutex_lock(&acm->mutex); if (acm->disconnected) goto disconnected; retval = usb_autopm_get_interface(acm->control); if (retval) goto error_get_interface; set_bit(TTY_NO_WRITE_SPLIT, &tty->flags); acm->control->needs_remote_wakeup = 1; acm->ctrlurb->dev = acm->dev; if (usb_submit_urb(acm->ctrlurb, GFP_KERNEL)) { dev_err(&acm->control->dev, "%s - usb_submit_urb(ctrl irq) failed\n", __func__); goto error_submit_urb; } acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS; if (acm_set_control(acm, acm->ctrlout) < 0 && (acm->ctrl_caps & USB_CDC_CAP_LINE)) goto error_set_control; usb_autopm_put_interface(acm->control); spin_lock_irq(&acm->read_lock); acm->throttled = 0; acm->throttle_req = 0; spin_unlock_irq(&acm->read_lock); if (acm_submit_read_urbs(acm, GFP_KERNEL)) goto error_submit_read_urbs; mutex_unlock(&acm->mutex); return 0; error_submit_read_urbs: acm->ctrlout = 0; acm_set_control(acm, acm->ctrlout); error_set_control: usb_kill_urb(acm->ctrlurb); error_submit_urb: usb_autopm_put_interface(acm->control); error_get_interface: disconnected: mutex_unlock(&acm->mutex); return retval; }
static void acm_tty_unthrottle(struct tty_struct *tty) { struct acm *acm = tty->driver_data; unsigned int was_throttled; spin_lock_irq(&acm->read_lock); was_throttled = acm->throttled; acm->throttled = 0; acm->throttle_req = 0; spin_unlock_irq(&acm->read_lock); if (was_throttled) acm_submit_read_urbs(acm, GFP_KERNEL); }
static int acm_resume(struct usb_interface *intf) { struct acm *acm = usb_get_intfdata(intf); struct acm_wb *wb; int rv = 0; int cnt; spin_lock_irq(&acm->read_lock); acm->susp_count -= 1; cnt = acm->susp_count; spin_unlock_irq(&acm->read_lock); if (cnt) return 0; mutex_lock(&acm->mutex); if (acm->port.count) { rv = usb_submit_urb(acm->ctrlurb, GFP_NOIO); spin_lock_irq(&acm->write_lock); if (acm->delayed_wb) { wb = acm->delayed_wb; acm->delayed_wb = NULL; spin_unlock_irq(&acm->write_lock); acm_start_wb(acm, wb); } else { spin_unlock_irq(&acm->write_lock); } /* * delayed error checking because we must * do the write path at all cost */ if (rv < 0) goto err_out; rv = acm_submit_read_urbs(acm, GFP_NOIO); } err_out: mutex_unlock(&acm->mutex); return rv; }
static int acm_resume(struct usb_interface *intf) { struct acm *acm = usb_get_intfdata(intf); struct urb *urb; int rv = 0; mutex_lock(&acm->mutex); spin_lock_irq(&acm->read_lock); spin_lock(&acm->write_lock); if (--acm->susp_count) goto out; if (acm->port.count) { rv = usb_submit_urb(acm->ctrlurb, GFP_ATOMIC); for (;;) { urb = usb_get_from_anchor(&acm->delayed); if (!urb) break; acm_start_wb(acm, urb->context); } /* * delayed error checking because we must * do the write path at all cost */ if (rv < 0) goto out; rv = acm_submit_read_urbs(acm, GFP_ATOMIC); } out: spin_unlock(&acm->write_lock); spin_unlock_irq(&acm->read_lock); mutex_unlock(&acm->mutex); return rv; }
static int acm_resume(struct usb_interface *intf) { struct acm *acm = usb_get_intfdata(intf); struct acm_wb *wb; int rv = 0; int cnt; spin_lock_irq(&acm->read_lock); acm->susp_count -= 1; cnt = acm->susp_count; spin_unlock_irq(&acm->read_lock); if (cnt) return 0; if (test_bit(ASYNCB_INITIALIZED, &acm->port.flags)) { rv = usb_submit_urb(acm->ctrlurb, GFP_NOIO); spin_lock_irq(&acm->write_lock); if (acm->delayed_wb) { wb = acm->delayed_wb; acm->delayed_wb = NULL; spin_unlock_irq(&acm->write_lock); acm_start_wb(acm, wb); } else { spin_unlock_irq(&acm->write_lock); } if (rv < 0) goto err_out; rv = acm_submit_read_urbs(acm, GFP_NOIO); } err_out: return rv; }
static int acm_tty_open(struct tty_struct *tty, struct file *filp) { struct acm *acm; int rv = -ENODEV; mutex_lock(&open_mutex); acm = acm_table[tty->index]; if (!acm || !acm->dev) goto out; else rv = 0; dev_dbg(&acm->control->dev, "%s\n", __func__); set_bit(TTY_NO_WRITE_SPLIT, &tty->flags); tty->driver_data = acm; tty_port_tty_set(&acm->port, tty); if (usb_autopm_get_interface(acm->control) < 0) goto early_bail; else acm->control->needs_remote_wakeup = 1; mutex_lock(&acm->mutex); if (acm->port.count++) { mutex_unlock(&acm->mutex); usb_autopm_put_interface(acm->control); goto out; } acm->ctrlurb->dev = acm->dev; if (usb_submit_urb(acm->ctrlurb, GFP_KERNEL)) { dev_err(&acm->control->dev, "%s - usb_submit_urb(ctrl irq) failed\n", __func__); goto bail_out; } if (0 > acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS) && (acm->ctrl_caps & USB_CDC_CAP_LINE)) goto bail_out; usb_autopm_put_interface(acm->control); /* * Unthrottle device in case the TTY was closed while throttled. */ spin_lock_irq(&acm->read_lock); acm->throttled = 0; acm->throttle_req = 0; spin_unlock_irq(&acm->read_lock); if (acm_submit_read_urbs(acm, GFP_KERNEL)) goto bail_out; set_bit(ASYNCB_INITIALIZED, &acm->port.flags); rv = tty_port_block_til_ready(&acm->port, tty, filp); mutex_unlock(&acm->mutex); out: mutex_unlock(&open_mutex); return rv; bail_out: acm->port.count--; mutex_unlock(&acm->mutex); usb_autopm_put_interface(acm->control); early_bail: mutex_unlock(&open_mutex); tty_port_tty_set(&acm->port, NULL); return -EIO; }
static int acm_tty_open(struct tty_struct *tty, struct file *filp) { struct acm *acm; int rv = -ENODEV; mutex_lock(&open_mutex); acm = acm_table[tty->index]; if (!acm || !acm->dev) goto out; else rv = 0; dev_dbg(&acm->control->dev, "%s\n", __func__); set_bit(TTY_NO_WRITE_SPLIT, &tty->flags); tty->driver_data = acm; tty_port_tty_set(&acm->port, tty); if (usb_autopm_get_interface(acm->control) < 0) goto early_bail; else acm->control->needs_remote_wakeup = 0; mutex_lock(&acm->mutex); if (acm->port.count++) { mutex_unlock(&acm->mutex); usb_autopm_put_interface(acm->control); goto out; } if (acm_submit_read_urbs(acm, GFP_KERNEL)) goto bail_out; acm->ctrlurb->dev = acm->dev; if (usb_submit_urb(acm->ctrlurb, GFP_KERNEL)) { dev_err(&acm->control->dev, "%s - usb_submit_urb(ctrl irq) failed\n", __func__); goto bail_out; } if (0 > acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS) && (acm->ctrl_caps & USB_CDC_CAP_LINE)) goto bail_out; // enorcar acm->state &= ~ACM_ABS_IDLE; if (0 > acm_set_comm_feature(acm, ACM_ABSTRACT_STATE, &acm->state) && (acm->ctrl_caps & USB_CDC_COMM_FEATURE)) goto bail_out; usb_autopm_put_interface(acm->control); set_bit(ASYNCB_INITIALIZED, &acm->port.flags); rv = tty_port_block_til_ready(&acm->port, tty, filp); mutex_unlock(&acm->mutex); out: mutex_unlock(&open_mutex); return rv; bail_out: acm->port.count--; mutex_unlock(&acm->mutex); usb_autopm_put_interface(acm->control); early_bail: mutex_unlock(&open_mutex); tty_port_tty_set(&acm->port, NULL); return -EIO; }
static int acm_resume(struct usb_interface *intf) { struct acm *acm = usb_get_intfdata(intf); int rv = 0; int cnt; #ifdef CONFIG_PM struct urb *res; #else struct acm_wb *wb; #endif if (!acm) { pr_err("%s: !acm\n", __func__); return -ENODEV; } spin_lock_irq(&acm->read_lock); if (acm->susp_count > 0) { acm->susp_count -= 1; cnt = acm->susp_count; } else { spin_unlock_irq(&acm->read_lock); return 0; } spin_unlock_irq(&acm->read_lock); if (cnt) return 0; mutex_lock(&acm->mutex); if (acm->port.count) { rv = usb_submit_urb(acm->ctrlurb, GFP_NOIO); spin_lock_irq(&acm->write_lock); #ifdef CONFIG_PM while ((res = usb_get_from_anchor(&acm->deferred))) { /* decrement ref count*/ usb_put_urb(res); rv = usb_submit_urb(res, GFP_ATOMIC); if (rv < 0) { dbg("usb_submit_urb(pending request)" " failed: %d", rv); usb_unanchor_urb(res); acm_write_done(acm, res->context); } } spin_unlock_irq(&acm->write_lock); #else if (acm->delayed_wb) { wb = acm->delayed_wb; acm->delayed_wb = NULL; spin_unlock_irq(&acm->write_lock); acm_start_wb(acm, wb); } else { spin_unlock_irq(&acm->write_lock); } #endif /* * delayed error checking because we must * do the write path at all cost */ if (rv < 0) goto err_out; rv = acm_submit_read_urbs(acm, GFP_NOIO); } err_out: mutex_unlock(&acm->mutex); return rv; }
static int acm_port_activate(struct tty_port *port, struct tty_struct *tty) { struct acm *acm = container_of(port, struct acm, port); int retval = -ENODEV; int i; dev_dbg(&acm->control->dev, "%s\n", __func__); mutex_lock(&acm->mutex); if (acm->disconnected) goto disconnected; retval = usb_autopm_get_interface(acm->control); if (retval) goto error_get_interface; /* * FIXME: Why do we need this? Allocating 64K of physically contiguous * memory is really nasty... */ set_bit(TTY_NO_WRITE_SPLIT, &tty->flags); acm->control->needs_remote_wakeup = 1; acm->ctrlurb->dev = acm->dev; if (usb_submit_urb(acm->ctrlurb, GFP_KERNEL)) { dev_err(&acm->control->dev, "%s - usb_submit_urb(ctrl irq) failed\n", __func__); goto error_submit_urb; } acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS; if (acm_set_control(acm, acm->ctrlout) < 0 && (acm->ctrl_caps & USB_CDC_CAP_LINE)) goto error_set_control; usb_autopm_put_interface(acm->control); /* * Unthrottle device in case the TTY was closed while throttled. */ spin_lock_irq(&acm->read_lock); acm->throttled = 0; acm->throttle_req = 0; spin_unlock_irq(&acm->read_lock); if (acm_submit_read_urbs(acm, GFP_KERNEL)) goto error_submit_read_urbs; mutex_unlock(&acm->mutex); return 0; error_submit_read_urbs: for (i = 0; i < acm->rx_buflimit; i++) usb_kill_urb(acm->read_urbs[i]); acm->ctrlout = 0; acm_set_control(acm, acm->ctrlout); error_set_control: usb_kill_urb(acm->ctrlurb); error_submit_urb: usb_autopm_put_interface(acm->control); error_get_interface: disconnected: mutex_unlock(&acm->mutex); return retval; }