Beispiel #1
0
/**
 * 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);
}
Beispiel #2
0
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);
}
Beispiel #3
0
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);
}
Beispiel #5
0
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);
}
Beispiel #6
0
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;
}
Beispiel #8
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);
}
Beispiel #9
0
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);
}
Beispiel #12
0
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);
}
Beispiel #13
0
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);
}