/** * gether_disconnect - notify network layer that USB link is inactive * @link: the USB link, on which gether_connect() was called * Context: irqs blocked * * This is called to deactivate endpoints and let the network layer know * the connection went inactive ("no carrier"). * * On return, the state is as if gether_connect() had never been called. * The endpoints are inactive, and accordingly without active USB I/O. * Pointers to endpoint descriptors and endpoint private data are nulled. */ void gether_disconnect(struct gether *link) { struct eth_dev *dev = link->ioport; struct usb_request *req; WARN_ON(!dev); if (!dev) return; DBG(dev, "%s\n", __func__); netif_stop_queue(dev->net); netif_carrier_off(dev->net); /* disable endpoints, forcing (synchronous) completion * of all pending i/o. then free the request objects * and forget about the endpoints. */ usb_ep_disable(link->in_ep); spin_lock(&dev->req_lock); while (!list_empty(&dev->tx_reqs)) { req = container_of(dev->tx_reqs.next, struct usb_request, list); list_del(&req->list); spin_unlock(&dev->req_lock); usb_ep_free_request(link->in_ep, req); spin_lock(&dev->req_lock); } spin_unlock(&dev->req_lock); link->in_ep->driver_data = NULL; link->in = NULL; usb_ep_disable(link->out_ep); usb_ep_fifo_flush(link->in_ep); usb_ep_fifo_flush(link->out_ep); spin_lock(&dev->req_lock); while (!list_empty(&dev->rx_reqs)) { req = container_of(dev->rx_reqs.next, struct usb_request, list); list_del(&req->list); spin_unlock(&dev->req_lock); usb_ep_free_request(link->out_ep, req); spin_lock(&dev->req_lock); } spin_unlock(&dev->req_lock); link->out_ep->driver_data = NULL; link->out = NULL; /* finish forgetting about this USB link episode */ dev->header_len = 0; dev->unwrap = NULL; dev->wrap = NULL; spin_lock(&dev->lock); dev->port_usb = NULL; link->ioport = NULL; spin_unlock(&dev->lock); }
void gether_disconnect(struct gether *link) { struct eth_dev *dev = link->ioport; struct usb_request *req; WARN_ON(!dev); if (!dev) return; DBG(dev, "%s\n", __func__); netif_stop_queue(dev->net); netif_carrier_off(dev->net); usb_ep_disable(link->in_ep); spin_lock(&dev->req_lock); while (!list_empty(&dev->tx_reqs)) { req = container_of(dev->tx_reqs.next, struct usb_request, list); list_del(&req->list); spin_unlock(&dev->req_lock); usb_ep_free_request(link->in_ep, req); spin_lock(&dev->req_lock); } spin_unlock(&dev->req_lock); link->in_ep->driver_data = NULL; link->in = NULL; usb_ep_disable(link->out_ep); usb_ep_fifo_flush(link->in_ep); usb_ep_fifo_flush(link->out_ep); spin_lock(&dev->req_lock); while (!list_empty(&dev->rx_reqs)) { req = container_of(dev->rx_reqs.next, struct usb_request, list); list_del(&req->list); spin_unlock(&dev->req_lock); usb_ep_free_request(link->out_ep, req); spin_lock(&dev->req_lock); } spin_unlock(&dev->req_lock); link->out_ep->driver_data = NULL; link->out = NULL; dev->header_len = 0; dev->unwrap = NULL; dev->wrap = NULL; spin_lock(&dev->lock); dev->port_usb = NULL; link->ioport = NULL; spin_unlock(&dev->lock); }
static long ep_ioctl(struct file *fd, unsigned code, unsigned long value) { struct ep_data *data = fd->private_data; int status; if ((status = get_ready_ep (fd->f_flags, data, false)) < 0) return status; spin_lock_irq (&data->dev->lock); if (likely (data->ep != NULL)) { switch (code) { case GADGETFS_FIFO_STATUS: status = usb_ep_fifo_status (data->ep); break; case GADGETFS_FIFO_FLUSH: usb_ep_fifo_flush (data->ep); break; case GADGETFS_CLEAR_HALT: status = usb_ep_clear_halt (data->ep); break; default: status = -ENOTTY; } } else status = -ENODEV; spin_unlock_irq (&data->dev->lock); mutex_unlock(&data->lock); return status; }
/** * gserial_disconnect - notify TTY I/O glue that USB link is inactive * @gser: the function, on which gserial_connect() was called * Context: any (usually from irq) * * This is called to deactivate endpoints and let the TTY layer know * that the connection went inactive ... not unlike "hangup". * * On return, the state is as if gserial_connect() had never been called; * there is no active USB I/O on these endpoints. */ void gserial_disconnect(struct gserial *gser) { struct gs_port *port = gser->ioport; unsigned long flags; pr_vdebug("%s\n", __func__); if (!port) return; /* tell the TTY glue not to do I/O here any more */ spin_lock_irqsave(&port->port_lock, flags); /* REVISIT as above: how best to track this? */ port->port_line_coding = gser->port_line_coding; port->port_usb = NULL; gser->ioport = NULL; #if 0 if (port->open_count > 0 || port->openclose) { wake_up_interruptible(&port->drain_wait); if (port->port_tty) tty_hangup(port->port_tty); } #endif spin_unlock_irqrestore(&port->port_lock, flags); /* disable endpoints, aborting down any active I/O */ usb_ep_fifo_flush(gser->out); usb_ep_fifo_flush(gser->in); usb_ep_disable(gser->out); gser->out->driver_data = NULL; usb_ep_disable(gser->in); gser->in->driver_data = NULL; /* finally, free any unused/unusable I/O buffers */ spin_lock_irqsave(&port->port_lock, flags); if (port->open_count == 0 && !port->openclose) gs_buf_free(&port->port_write_buf); gs_free_requests(gser->out, &port->read_pool); gs_free_requests(gser->out, &port->read_queue); gs_free_requests(gser->in, &port->write_pool); spin_unlock_irqrestore(&port->port_lock, flags); }
void gserial_disconnect(struct gserial *gser) { struct gs_port *port = gser->ioport; unsigned long flags; if (!port) return; spin_lock_irqsave(&port->port_lock, flags); port->port_line_coding = gser->port_line_coding; port->port_usb = NULL; gser->ioport = NULL; if (port->open_count > 0 || port->openclose) { wake_up_interruptible(&port->drain_wait); if (port->port_tty) tty_hangup(port->port_tty); } spin_unlock_irqrestore(&port->port_lock, flags); usb_ep_fifo_flush(gser->out); usb_ep_fifo_flush(gser->in); usb_ep_disable(gser->out); gser->out->driver_data = NULL; usb_ep_disable(gser->in); gser->in->driver_data = NULL; spin_lock_irqsave(&port->port_lock, flags); if (port->open_count == 0 && !port->openclose) gs_buf_free(&port->port_write_buf); gs_free_requests(gser->out, &port->read_pool); gs_free_requests(gser->out, &port->read_queue); gs_free_requests(gser->in, &port->write_pool); spin_unlock_irqrestore(&port->port_lock, flags); }
static void mtp_int_complete(struct usb_ep *ep, struct usb_request *req) { mtp_debug("status is %d %d\n", req->status, req->actual); if (req->status == -ECONNRESET) usb_ep_fifo_flush(ep); if (req->status != 0) mtp_err("status is %d %p len=%d\n", req->status, req, req->actual); g_usb_mtp_context.intr_in_busy = 0; return; }
static void gser_disable(struct usb_function *f) { struct f_gser *gser = func_to_gser(f); struct usb_composite_dev *cdev = f->config->cdev; DBG(cdev, "generic ttyGS%d deactivated\n", gser->port_num); gport_disconnect(gser); #ifdef CONFIG_MODEM_SUPPORT usb_ep_fifo_flush(gser->notify); usb_ep_disable(gser->notify); #endif gser->online = 0; }
static void mtp_out_complete(struct usb_ep *ep, struct usb_request *req) { mtp_debug("status is %d %p %d\n", req->status, req, req->actual); if (req->status == 0) { req_put(&g_usb_mtp_context.rx_done_reqs, req); } else { mtp_debug("status is %d %p len=%d\n", req->status, req, req->actual); g_usb_mtp_context.error = 1; if (req->status == -ECONNRESET) usb_ep_fifo_flush(ep); req_put(&g_usb_mtp_context.rx_reqs, req); } wake_up(&g_usb_mtp_context.rx_wq); }
static void mtp_in_complete(struct usb_ep *ep, struct usb_request *req) { mtp_debug("status is %d %p %d\n", req->status, req, req->actual); if (req->status == -ECONNRESET) usb_ep_fifo_flush(ep); if (req->status != 0) { g_usb_mtp_context.error = 1; mtp_err("status is %d %p len=%d\n", req->status, req, req->actual); } req_put(&g_usb_mtp_context.tx_reqs, req); wake_up(&g_usb_mtp_context.tx_wq); }
static void mtp_function_disable(struct usb_function *f) { printk(KERN_DEBUG "%s(): disabled\n", __func__); g_usb_mtp_context.online = 0; g_usb_mtp_context.cancel = 1; g_usb_mtp_context.ctl_cancel = 1; g_usb_mtp_context.error = 1; usb_ep_fifo_flush(g_usb_mtp_context.bulk_in); usb_ep_fifo_flush(g_usb_mtp_context.bulk_out); usb_ep_fifo_flush(g_usb_mtp_context.intr_in); usb_ep_disable(g_usb_mtp_context.bulk_in); usb_ep_disable(g_usb_mtp_context.bulk_out); usb_ep_disable(g_usb_mtp_context.intr_in); g_usb_mtp_context.cur_read_req = 0; g_usb_mtp_context.read_buf = 0; g_usb_mtp_context.data_len = 0; /* readers may be blocked waiting for us to go online */ wake_up(&g_usb_mtp_context.rx_wq); wake_up(&g_usb_mtp_context.tx_wq); wake_up(&g_usb_mtp_context.ctl_rx_wq); wake_up(&g_usb_mtp_context.ctl_tx_wq); }
static void mtp_out_complete(struct usb_ep *ep, struct usb_request *req) { mtp_debug("status is %d %p %d\n", req->status, req, req->actual); if (req->status == 0) { req_put(&g_usb_mtp_context.rx_done_reqs, req); } else { mtp_err("status is %d %p len=%d\n", req->status, req, req->actual); g_usb_mtp_context.error = 1; if (req->status == -ECONNRESET) { #ifdef CONFIG_LGE_USB_GADGET_MTP_DRIVER lg_mtp_debug("LG_FW : BULK OUT DATA Flush!!\n"); #endif usb_ep_fifo_flush(ep); } req_put(&g_usb_mtp_context.rx_reqs, req); } wake_up(&g_usb_mtp_context.rx_wq); }
static void gs_close(struct tty_struct *tty, struct file *file) { struct gs_port *port = tty->driver_data; struct gserial *gser; spin_lock_irq(&port->port_lock); if (port->open_count != 1) { if (port->open_count == 0) WARN_ON(1); else --port->open_count; goto exit; } pr_debug("gs_close: ttyGS%d (%p,%p) ...\n", port->port_num, tty, file); /* mark port as closing but in use; we can drop port lock * and sleep if necessary */ port->openclose = true; port->open_count = 0; gser = port->port_usb; if (gser && gser->disconnect) gser->disconnect(gser); /* wait for circular write buffer to drain, disconnect, or at * most GS_CLOSE_TIMEOUT seconds; then discard the rest */ if (gs_buf_data_avail(&port->port_write_buf) > 0 && gser) { spin_unlock_irq(&port->port_lock); wait_event_interruptible_timeout(port->drain_wait, gs_writes_finished(port), GS_CLOSE_TIMEOUT * HZ); spin_lock_irq(&port->port_lock); gser = port->port_usb; } /* Iff we're disconnected, there can be no I/O in flight so it's * ok to free the circular buffer; else just scrub it. And don't * let the push work queue fire again until we're re-opened. */ if (gser == NULL) gs_buf_free(&port->port_write_buf); else gs_buf_clear(&port->port_write_buf); tty->driver_data = NULL; port->port_tty = NULL; port->openclose = false; pr_debug("gs_close: ttyGS%d (%p,%p) done!\n", port->port_num, tty, file); wake_up_interruptible(&port->close_wait); /* * Freeing the previously queued requests as they are * allocated again as a part of gs_open() */ if (port->port_usb) { spin_unlock_irq(&port->port_lock); usb_ep_fifo_flush(gser->out); usb_ep_fifo_flush(gser->in); spin_lock_irq(&port->port_lock); gs_free_requests(gser->out, &port->read_queue, NULL); gs_free_requests(gser->out, &port->read_pool, NULL); gs_free_requests(gser->in, &port->write_pool, NULL); } port->read_allocated = port->read_started = port->write_allocated = port->write_started = 0; exit: spin_unlock_irq(&port->port_lock); }
static void gs_close(struct tty_struct *tty, struct file *file) { struct gs_port *port = tty->driver_data; struct gserial *gser; spin_lock_irq(&port->port_lock); if (port->open_count != 1) { if (port->open_count == 0) WARN_ON(1); else --port->open_count; goto exit; } pr_debug("gs_close: ttyGS%d (%p,%p) ...\n", port->port_num, tty, file); port->openclose = true; port->open_count = 0; gser = port->port_usb; if (gser && gser->disconnect) gser->disconnect(gser); if (gs_buf_data_avail(&port->port_write_buf) > 0 && gser) { spin_unlock_irq(&port->port_lock); wait_event_interruptible_timeout(port->drain_wait, gs_writes_finished(port), GS_CLOSE_TIMEOUT * HZ); spin_lock_irq(&port->port_lock); gser = port->port_usb; } if (gser == NULL) gs_buf_free(&port->port_write_buf); else gs_buf_clear(&port->port_write_buf); tty->driver_data = NULL; port->port_tty = NULL; port->openclose = false; pr_debug("gs_close: ttyGS%d (%p,%p) done!\n", port->port_num, tty, file); wake_up_interruptible(&port->close_wait); if (port->port_usb) { spin_unlock_irq(&port->port_lock); usb_ep_fifo_flush(gser->out); usb_ep_fifo_flush(gser->in); spin_lock_irq(&port->port_lock); gs_free_requests(gser->out, &port->read_queue, NULL); gs_free_requests(gser->out, &port->read_pool, NULL); gs_free_requests(gser->in, &port->write_pool, NULL); } port->read_allocated = port->read_started = port->write_allocated = port->write_started = 0; exit: spin_unlock_irq(&port->port_lock); }