/* destroy an USB endpoint */ void fhci_ep0_free(struct fhci_usb *usb) { struct endpoint *ep; int size; ep = usb->ep0; if (ep) { if (ep->td_base) cpm_muram_free(cpm_muram_offset(ep->td_base)); if (kfifo_initialized(&ep->conf_frame_Q)) { size = cq_howmany(&ep->conf_frame_Q); for (; size; size--) { struct packet *pkt = cq_get(&ep->conf_frame_Q); kfree(pkt); } cq_delete(&ep->conf_frame_Q); } if (kfifo_initialized(&ep->empty_frame_Q)) { size = cq_howmany(&ep->empty_frame_Q); for (; size; size--) { struct packet *pkt = cq_get(&ep->empty_frame_Q); kfree(pkt); } cq_delete(&ep->empty_frame_Q); } if (kfifo_initialized(&ep->dummy_packets_Q)) { size = cq_howmany(&ep->dummy_packets_Q); for (; size; size--) { u8 *buff = cq_get(&ep->dummy_packets_Q); kfree(buff); } cq_delete(&ep->dummy_packets_Q); } kfree(ep); usb->ep0 = NULL; } }
static int iio_kfifo_write(struct iio_buffer *r, size_t n, const char __user *buf) { struct iio_kfifo *kf = iio_to_kfifo(r); int ret, copied; mutex_lock(&kf->user_lock); if (!kfifo_initialized(&kf->kf) || n < kfifo_esize(&kf->kf)) ret = -EINVAL; else ret = kfifo_from_user(&kf->kf, buf, n, &copied); mutex_unlock(&kf->user_lock); if (ret) return ret; return copied; }
static int iio_read_kfifo(struct iio_buffer *r, size_t n, char __user *buf) { int ret, copied; struct iio_kfifo *kf = iio_to_kfifo(r); if (mutex_lock_interruptible(&kf->user_lock)) return -ERESTARTSYS; if (!kfifo_initialized(&kf->kf) || n < kfifo_esize(&kf->kf)) ret = -EINVAL; else ret = kfifo_to_user(&kf->kf, buf, n, &copied); mutex_unlock(&kf->user_lock); if (ret < 0) return ret; return copied; }
/* * gs_open sets up the link between a gs_port and its associated TTY. * That link is broken *only* by TTY close(), and all driver methods * know that. */ static int gs_open(struct tty_struct *tty, struct file *file) { int port_num = tty->index; struct gs_port *port; int status; do { mutex_lock(&ports[port_num].lock); port = ports[port_num].port; if (!port) status = -ENODEV; else { spin_lock_irq(&port->port_lock); /* already open? Great. */ if (port->port.count) { status = 0; port->port.count++; /* currently opening/closing? wait ... */ } else if (port->openclose) { status = -EBUSY; /* ... else we do the work */ } else { status = -EAGAIN; port->openclose = true; } spin_unlock_irq(&port->port_lock); } mutex_unlock(&ports[port_num].lock); switch (status) { default: /* fully handled */ return status; case -EAGAIN: /* must do the work */ break; case -EBUSY: /* wait for EAGAIN task to finish */ msleep(1); /* REVISIT could have a waitchannel here, if * concurrent open performance is important */ break; } } while (status != -EAGAIN); /* Do the "real open" */ spin_lock_irq(&port->port_lock); /* allocate circular buffer on first open */ if (!kfifo_initialized(&port->port_write_buf)) { spin_unlock_irq(&port->port_lock); status = kfifo_alloc(&port->port_write_buf, WRITE_BUF_SIZE, GFP_KERNEL); spin_lock_irq(&port->port_lock); if (status) { pr_debug("gs_open: ttyGS%d (%p,%p) no buffer\n", port->port_num, tty, file); port->openclose = false; goto exit_unlock_port; } } /* REVISIT if REMOVED (ports[].port NULL), abort the open * to let rmmod work faster (but this way isn't wrong). */ /* REVISIT maybe wait for "carrier detect" */ tty->driver_data = port; port->port.tty = tty; port->port.count = 1; port->openclose = false; /* if connected, start the I/O stream */ if (port->port_usb) { struct gserial *gser = port->port_usb; pr_debug("gs_open: start ttyGS%d\n", port->port_num); gs_start_io(port); if (gser->connect) gser->connect(gser); } pr_debug("gs_open: ttyGS%d (%p,%p)\n", port->port_num, tty, file); status = 0; exit_unlock_port: spin_unlock_irq(&port->port_lock); return status; }