int data_bridge_write(unsigned int id, struct sk_buff *skb) { int result; int size = skb->len; int pending; struct urb *txurb; struct timestamp_info *info = (struct timestamp_info *)skb->cb; struct data_bridge *dev = __dev[id]; struct bridge *brdg; if (!dev || !dev->brdg || dev->err || !usb_get_intfdata(dev->intf)) return -ENODEV; brdg = dev->brdg; if (!brdg) return -ENODEV; dev_dbg(&dev->udev->dev, "%s: write (%d bytes)\n", __func__, skb->len); result = usb_autopm_get_interface(dev->intf); if (result < 0) { dev_err(&dev->udev->dev, "%s: resume failure\n", __func__); goto error; } txurb = usb_alloc_urb(0, GFP_KERNEL); if (!txurb) { dev_err(&dev->udev->dev, "%s: error allocating read urb\n", __func__); result = -ENOMEM; goto error; } /* store dev pointer in skb */ info->dev = dev; info->tx_queued = get_timestamp(); usb_fill_bulk_urb(txurb, dev->udev, dev->bulk_out, skb->data, skb->len, data_bridge_write_cb, skb); if (test_bit(SUSPENDED, &dev->flags)) { usb_anchor_urb(txurb, &dev->delayed); goto free_urb; } pending = atomic_inc_return(&dev->pending_txurbs); usb_anchor_urb(txurb, &dev->tx_active); if (atomic_read(&dev->pending_txurbs) % tx_urb_mult) txurb->transfer_flags |= URB_NO_INTERRUPT; result = usb_submit_urb(txurb, GFP_KERNEL); if (result < 0) { usb_unanchor_urb(txurb); atomic_dec(&dev->pending_txurbs); dev_err(&dev->udev->dev, "%s: submit URB error %d\n", __func__, result); goto free_urb; } dev->to_modem++; dev_dbg(&dev->udev->dev, "%s: pending_txurbs: %u\n", __func__, pending); /* flow control: last urb submitted but return -EBUSY */ if (fctrl_support && pending > fctrl_en_thld) { set_bit(TX_THROTTLED, &brdg->flags); dev->tx_throttled_cnt++; pr_debug_ratelimited("%s: enable flow ctrl pend txurbs:%u\n", __func__, pending); return -EBUSY; } return size; free_urb: usb_free_urb(txurb); error: dev->txurb_drp_cnt++; usb_autopm_put_interface(dev->intf); return result; }
/*=========================================================================== METHOD: QCUSBNetAutoPMThread (Public Method) DESCRIPTION: Handle device Auto PM state asynchronously Handle network packet transmission asynchronously PARAMETERS pData [ I ] - Pointer to sAutoPM struct RETURN VALUE: int - 0 for success Negative errno for error ===========================================================================*/ static int QCUSBNetAutoPMThread( void * pData ) { unsigned long activeURBflags, URBListFlags; sURBList * pURBListEntry; int status; struct usb_device * pUdev; sAutoPM * pAutoPM = (sAutoPM *)pData; if (pAutoPM == NULL) { DBG( "passed null pointer\n" ); return -EINVAL; } pUdev = interface_to_usbdev( pAutoPM->mpIntf ); DBG( "traffic thread started\n" ); while (pAutoPM->mbExit == false) { // Wait for someone to poke us wait_for_completion_interruptible( &pAutoPM->mThreadDoWork ); // Time to exit? if (pAutoPM->mbExit == true) { // Stop activeURB spin_lock_irqsave( &pAutoPM->mActiveURBLock, activeURBflags ); if (pAutoPM->mpActiveURB != NULL) { usb_kill_urb( pAutoPM->mpActiveURB ); } // Will be freed in callback function spin_unlock_irqrestore( &pAutoPM->mActiveURBLock, activeURBflags ); // Cleanup URB List spin_lock_irqsave( &pAutoPM->mURBListLock, URBListFlags ); pURBListEntry = pAutoPM->mpURBList; while (pURBListEntry != NULL) { pAutoPM->mpURBList = pAutoPM->mpURBList->mpNext; usb_free_urb( pURBListEntry->mpURB ); kfree( pURBListEntry ); pURBListEntry = pAutoPM->mpURBList; } spin_unlock_irqrestore( &pAutoPM->mURBListLock, URBListFlags ); break; } // Is our URB active? spin_lock_irqsave( &pAutoPM->mActiveURBLock, activeURBflags ); // EAGAIN used to signify callback is done if (IS_ERR( pAutoPM->mpActiveURB ) && PTR_ERR( pAutoPM->mpActiveURB ) == -EAGAIN ) { pAutoPM->mpActiveURB = NULL; // Restore IRQs so task can sleep spin_unlock_irqrestore( &pAutoPM->mActiveURBLock, activeURBflags ); // URB is done, decrement the Auto PM usage count usb_autopm_put_interface( pAutoPM->mpIntf ); // Lock ActiveURB again spin_lock_irqsave( &pAutoPM->mActiveURBLock, activeURBflags ); } if (pAutoPM->mpActiveURB != NULL) { // There is already a URB active, go back to sleep spin_unlock_irqrestore( &pAutoPM->mActiveURBLock, activeURBflags ); continue; } // Is there a URB waiting to be submitted? spin_lock_irqsave( &pAutoPM->mURBListLock, URBListFlags ); if (pAutoPM->mpURBList == NULL) { // No more URBs to submit, go back to sleep spin_unlock_irqrestore( &pAutoPM->mURBListLock, URBListFlags ); spin_unlock_irqrestore( &pAutoPM->mActiveURBLock, activeURBflags ); continue; } // Pop an element pURBListEntry = pAutoPM->mpURBList; pAutoPM->mpURBList = pAutoPM->mpURBList->mpNext; spin_unlock_irqrestore( &pAutoPM->mURBListLock, URBListFlags ); // Set ActiveURB pAutoPM->mpActiveURB = pURBListEntry->mpURB; spin_unlock_irqrestore( &pAutoPM->mActiveURBLock, activeURBflags ); // Tell autopm core we need device woken up status = usb_autopm_get_interface( pAutoPM->mpIntf ); if (status < 0) { DBG( "unable to autoresume interface: %d\n", status ); // likely caused by device going from autosuspend -> full suspend if (status == -EPERM) { #if (LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,33 )) pUdev->auto_pm = 0; #endif QCSuspend( pAutoPM->mpIntf, PMSG_SUSPEND ); } // Add pURBListEntry back onto pAutoPM->mpURBList spin_lock_irqsave( &pAutoPM->mURBListLock, URBListFlags ); pURBListEntry->mpNext = pAutoPM->mpURBList; pAutoPM->mpURBList = pURBListEntry; spin_unlock_irqrestore( &pAutoPM->mURBListLock, URBListFlags ); spin_lock_irqsave( &pAutoPM->mActiveURBLock, activeURBflags ); pAutoPM->mpActiveURB = NULL; spin_unlock_irqrestore( &pAutoPM->mActiveURBLock, activeURBflags ); // Go back to sleep continue; } // Submit URB status = usb_submit_urb( pAutoPM->mpActiveURB, GFP_KERNEL ); if (status < 0) { // Could happen for a number of reasons DBG( "Failed to submit URB: %d. Packet dropped\n", status ); spin_lock_irqsave( &pAutoPM->mActiveURBLock, activeURBflags ); usb_free_urb( pAutoPM->mpActiveURB ); pAutoPM->mpActiveURB = NULL; spin_unlock_irqrestore( &pAutoPM->mActiveURBLock, activeURBflags ); usb_autopm_put_interface( pAutoPM->mpIntf ); // Loop again complete( &pAutoPM->mThreadDoWork ); } kfree( pURBListEntry ); } DBG( "traffic thread exiting\n" ); pAutoPM->mpThread = NULL; return 0; }
/*=========================================================================== METHOD: QCUSBNetOpen (Public Method) DESCRIPTION: Wrapper to usbnet_open, correctly handling autosuspend Start AutoPM thread PARAMETERS pNet [ I ] - Pointer to net device RETURN VALUE: int - 0 for success Negative errno for error ===========================================================================*/ int QCUSBNetOpen( struct net_device * pNet ) { int status = 0; struct sQCUSBNet * pQCDev; struct usbnet * pDev = netdev_priv( pNet ); if (pDev == NULL) { DBG( "failed to get usbnet device\n" ); return -ENXIO; } pQCDev = (sQCUSBNet *)pDev->data[0]; if (pQCDev == NULL) { DBG( "failed to get QMIDevice\n" ); return -ENXIO; } DBG( "\n" ); // Start the AutoPM thread pQCDev->mAutoPM.mpIntf = pQCDev->mpIntf; pQCDev->mAutoPM.mbExit = false; pQCDev->mAutoPM.mpURBList = NULL; pQCDev->mAutoPM.mpActiveURB = NULL; spin_lock_init( &pQCDev->mAutoPM.mURBListLock ); spin_lock_init( &pQCDev->mAutoPM.mActiveURBLock ); init_completion( &pQCDev->mAutoPM.mThreadDoWork ); pQCDev->mAutoPM.mpThread = kthread_run( QCUSBNetAutoPMThread, &pQCDev->mAutoPM, "QCUSBNetAutoPMThread" ); if (IS_ERR( pQCDev->mAutoPM.mpThread )) { DBG( "AutoPM thread creation error\n" ); return PTR_ERR( pQCDev->mAutoPM.mpThread ); } // Allow traffic QClearDownReason( pQCDev, NET_IFACE_STOPPED ); // Pass to usbnet_open if defined if (pQCDev->mpUSBNetOpen != NULL) { status = pQCDev->mpUSBNetOpen( pNet ); // If usbnet_open was successful enable Auto PM if (status == 0) { #if (LINUX_VERSION_CODE < KERNEL_VERSION( 2,6,33 )) usb_autopm_enable( pQCDev->mpIntf ); #else usb_autopm_put_interface( pQCDev->mpIntf ); #endif } } else { DBG( "no USBNetOpen defined\n" ); } return status; }
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 rmnet_ctrl_set_itc( struct rmnet_ctrl_dev *dev, int value ) { int ret = 0; int enable = 0; struct usb_device *udev; if (!dev) { pr_info("[%s] dev is null\n", __func__); return -ENODEV; } if (!dev->intf) { pr_info("[%s] intf is null\n", __func__); return -ENODEV; } udev = interface_to_usbdev(dev->intf); switch(value) { case 1://enable enable = 1; break; case 0://disable enable = 0; break; default://other pr_info("[%s][%s] value=[%d]\n", __func__, dev->name, value); return -ENODEV; } pr_info("[%s][%s] mutex_lock\n", __func__, dev->name); mutex_lock(&dev->dev_lock); if ( ! ( dev->is_opened && dev->resp_available ) ) { pr_err("[%s] is_opened=[%d], resp_available=[%d]\n", __func__, dev->is_opened, dev->resp_available); mutex_unlock(&dev->dev_lock); return -ENODEV; } pr_info("[%s] is_opened=[%d], resp_available=[%d]\n", __func__, dev->is_opened, dev->resp_available); pr_info("[%s] enable_shorten_itc_count:%d enable:%d\n", __func__, enable_shorten_itc_count, enable); if ( enable ) { if (enable_shorten_itc_count == 0) { ret = usb_autopm_get_interface(dev->intf); if (ret < 0) { pr_info("[%s] Unable to resume interface: %d\n", __func__, ret); mutex_unlock(&dev->dev_lock); return -ENODEV; } pr_info("[%s][%s] usb_set_interrupt_latency(1)+\n", __func__, dev->name); ret = usb_set_interrupt_latency(udev, HSIC_FAST_INTERRUPT_LATENCY); pr_info("[%s][%s] usb_set_interrupt_latency-\n", __func__, dev->name); if ( dev->intf ) usb_autopm_put_interface(dev->intf); else pr_err("[%s]dev->intf=NULL\n", __func__); } enable_shorten_itc_count++; } else { if ( enable_shorten_itc_count < 1 ) { pr_info("[%s][%s] set_shorten_interrupt_latency_count is %d\n", __func__, dev->name, enable_shorten_itc_count); } else { enable_shorten_itc_count--; if (enable_shorten_itc_count == 0) { ret = usb_autopm_get_interface(dev->intf); if (ret < 0) { pr_info("[%s] Unable to resume interface: %d\n", __func__, ret); mutex_unlock(&dev->dev_lock); return -ENODEV; } pr_info("[%s][%s] usb_set_interrupt_latency(6)+\n", __func__, dev->name); ret = usb_set_interrupt_latency(udev, HSIC_SLOW_INTERRUPT_LATENCY); pr_info("[%s][%s] usb_set_interrupt_latency-\n", __func__, dev->name); if ( dev->intf ) usb_autopm_put_interface(dev->intf); else pr_err("[%s]dev->intf=NULL\n", __func__); } } } mutex_unlock(&dev->dev_lock); pr_info("[%s][%s] mutex_unlock\n", __func__, dev->name); return ret; }
static int acm_tty_open(struct tty_struct *tty, struct file *filp) { struct acm *acm; int rv = -ENODEV; int i; dbg("Entering acm_tty_open."); mutex_lock(&open_mutex); acm = acm_table[tty->index]; if (!acm || !acm->dev) goto err_out; else rv = 0; 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++) { usb_autopm_put_interface(acm->control); goto done; } acm->ctrlurb->dev = acm->dev; if (usb_submit_urb(acm->ctrlurb, GFP_KERNEL)) { dbg("usb_submit_urb(ctrl irq) failed"); 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 full_bailout; usb_autopm_put_interface(acm->control); INIT_LIST_HEAD(&acm->spare_read_urbs); INIT_LIST_HEAD(&acm->spare_read_bufs); INIT_LIST_HEAD(&acm->filled_read_bufs); for (i = 0; i < acm->rx_buflimit; i++) list_add(&(acm->ru[i].list), &acm->spare_read_urbs); for (i = 0; i < acm->rx_buflimit; i++) list_add(&(acm->rb[i].list), &acm->spare_read_bufs); acm->throttle = 0; set_bit(ASYNCB_INITIALIZED, &acm->port.flags); rv = tty_port_block_til_ready(&acm->port, tty, filp); tasklet_schedule(&acm->urb_task); done: mutex_unlock(&acm->mutex); err_out: mutex_unlock(&open_mutex); return rv; full_bailout: usb_kill_urb(acm->ctrlurb); bail_out: usb_autopm_put_interface(acm->control); acm->port.count--; mutex_unlock(&acm->mutex); early_bail: mutex_unlock(&open_mutex); tty_port_tty_set(&acm->port, NULL); return -EIO; }
/* static void ss801u_write_bulk_callback(struct urb *urb) { usb_ss801u *dev; dev = (usb_ss801u *)urb->context; // sync/async unlink faults aren't errors // if (urb->status) { if(!(urb->status == -ENOENT || urb->status == -ECONNRESET || urb->status == -ESHUTDOWN)) err("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); Egis_Reset_device(dev); spin_lock(&dev->err_lock); dev->errors = urb->status; spin_unlock(&dev->err_lock); } // free up our allocated buffer // usb_buffer_free(urb->dev, urb->transfer_buffer_length, urb->transfer_buffer, urb->transfer_dma); up(&dev->limit_sem); } */ static ssize_t ss801u_write(struct file *file, const char *user_buffer, size_t count, loff_t *ppos) { printk(KERN_INFO "Patrick-> ss801u_write start\n"); printk(KERN_INFO "Patrick-> ss801u_write finish\n"); //*/ //--------------- CASE1 : return only -----------------------// //-----------------------------------------------------------// return -ENOSYS; // function not implement #if 0 /*---------------- CASE2 : bulk write -----------------------*/ /*-----------------------------------------------------------*/ usb_ss801u *dev; int retval = 0; struct urb *urb = NULL; char *buf = NULL; size_t writesize = min(count, (size_t)MAX_TRANSFER); dev = (usb_ss801u *)file->private_data; if (count == 0) goto exit; if (down_interruptible(&dev->limit_sem)) { retval = -ERESTARTSYS; goto exit; } spin_lock_irq(&dev->err_lock); retval = dev->errors; if (retval < 0) { dev->errors = 0; retval = (retval == -EPIPE) ? retval : -EIO; } spin_unlock_irq(&dev->err_lock); if (retval < 0) goto error; /*----- create a urb, and a buffer for it, and copy the data to the urb -----*/ urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) { retval = -ENOMEM; goto error; } buf = usb_buffer_alloc(dev->udev, writesize, GFP_KERNEL, &urb->transfer_dma); if (!buf) { retval = -ENOMEM; goto error; } if (copy_from_user(buf, user_buffer, writesize)) { retval = -EFAULT; goto error; } /*----- this lock makes sure we don't submit URBs to gone devices -----*/ /*---------------------------------------------------------------------*/ mutex_lock(&dev->io_mutex); if (!dev->interface) { /* disconnect() was called */ mutex_unlock(&dev->io_mutex); retval = -ENODEV; goto error; } /*----- To NOT go to suspend -----*/ usb_autopm_get_interface(dev->interface); /*----- initialize the urb properly -----*/ usb_fill_bulk_urb(urb, dev->udev, usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr), buf, writesize, ss801u_write_bulk_callback, dev); urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; /*usb_anchor_urb(urb, &dev->submitted);*/ /*----- send the data out the bulk port -----*/ retval = usb_submit_urb(urb, GFP_KERNEL); /*----- Auto suspend -----*/ usb_autopm_put_interface(dev->interface); mutex_unlock(&dev->io_mutex); /*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/ if (retval) { Egis_Reset_device(dev); err("%s - failed submitting write urb, error %d", retval, retval); goto error_unanchor; } /*----- release our reference to this urb, the USB core will eventually free it entirely -----*/ usb_free_urb(urb); return writesize; error_unanchor: usb_unanchor_urb(urb); error: if (urb) { usb_buffer_free(dev->udev, writesize, buf, urb->transfer_dma); usb_free_urb(urb); } up(&dev->limit_sem); exit: return retval; #endif }
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; }
static int ss801u_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { usb_ss801u *dev; int argerr = 0; int retval = 0; u32 tmp; unsigned n_ioc = 0; struct spi_ioc_transfer *ioc = NULL; printk(KERN_INFO "Patrick-> ss801u_ioctl start\n"); dev = (usb_ss801u *)file->private_data; pr_debug("ioctl Start!!\n"); /* ================================ Check input cmd and arg ======================================== */ /* ================================================================================================= */ /* ---- Check control code ---- */ if (EGIS_IOCTL_MAXNR <= _IOC_NR(cmd)) return -ENOTTY; /* ================================== Switch control code ========================================== */ /* ================================================================================================= */ mutex_lock(&dev->io_mutex); if (!dev->interface) { /* disconnect() was called */ retval = -ENODEV; goto exit; } /* ----- Avoid suspend ----- */ usb_autopm_get_interface(dev->interface); /* ---- Check argument buffer ---- */ if (_IOC_READ & _IOC_DIR(cmd)) { /* access_ok : 1 means success */ /* VERIFY_WRITE : A buffer that SDK reads means drivers should write it. */ argerr = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd)); } if (_IOC_WRITE & _IOC_DIR(cmd)) argerr = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd)); if (argerr) return -EINVAL; if (SPI_IOC_MAGIC == _IOC_TYPE(cmd)) { tmp = _IOC_SIZE(cmd); if ((tmp % sizeof(struct spi_ioc_transfer)) != 0) { retval = -EINVAL; goto done; } n_ioc = tmp / sizeof(struct spi_ioc_transfer); pr_debug("%s->%s: Got %d spi_ioc_transfer Packages\n", __FILE__, __func__, n_ioc); if (n_ioc == 0) goto done; /* copy into scratch area */ ioc = kmalloc(tmp, GFP_KERNEL); if (!ioc) { retval = -ENOMEM; goto done; } if (__copy_from_user(ioc, (void __user *)arg, tmp)) { kfree(ioc); retval = -EFAULT; goto done; } switch (ioc->opcode) { case JADE_REGISTER_MASSREAD: printk(KERN_INFO "Patrick-> JADE_REGISTER_MASSREAD start\n"); if (ioc->rx_buf) { if (!access_ok(VERIFY_WRITE, (u8 __user *) (uintptr_t) ioc->rx_buf, ioc->len)) { pr_debug("!access_ok on JADE_REGISTER_MASSREAD!!"); retval = -EACCES; goto done; } } retval = ES603_IO_Bulk_Read(dev, ioc, n_ioc); printk(KERN_INFO "Patrick-> JADE_REGISTER_MASSREAD finish\n"); break; case JADE_REGISTER_MASSWRITE: printk(KERN_INFO "Patrick-> JADE_REGISTER_MASSWRITE start\n"); retval = ES603_IO_Bulk_Write(dev, ioc, n_ioc); printk(KERN_INFO "Patrick-> JADE_REGISTER_MASSWRITE finish\n"); break; case JADE_GET_ONE_IMG: printk(KERN_INFO "Patrick-> JADE_GET_ONE_IMG start\n"); retval = es603_io_bulk_get_image(dev, ioc, n_ioc); printk(KERN_INFO "Patrick-> JADE_GET_ONE_IMG finish\n"); break; case JADE_GET_FULL_IMAGE2: printk(KERN_INFO "Patrick-> JADE_GET_FULL_IMAGE2 start\n"); retval = es603_io_bulk_get_full_image(dev, ioc, n_ioc); printk(KERN_INFO "Patrick-> JADE_GET_FULL_IMAGE2 finish\n"); break; default: retval = -EFAULT; } done: kfree(ioc); } else if (EGIS_IOCTL_MAGIC == _IOC_TYPE(cmd)) { switch (cmd) { /* -------------------- ss801u SCSI CMD XFER ---------------------- */ /* ---------------------------------------------------------------- */ case EGIS_IOCTL_SCSI_READ: { retval = Egis_IO_SCSI_Read(dev, arg); break; } case EGIS_IOCTL_SCSI_WRITE: { retval = Egis_IO_SCSI_Write(dev, arg); break; } case EGIS_IOCTL_SET_NORMALMODE_REG: { EgisMsg(dev->bPrintDbgMsg, KERN_INFO, "=ioctl=EGIS_IOCTL_SET_NORMALMODE_REG "); if (copy_from_user((void *)&dev->normalCBW, (void *)arg, CBW_SIZE)) { EgisMsg(dev->bPrintDbgMsg, KERN_ERR, "=ioctl=EGIS_IOCTL_SET_NORMALMODE_REG copy from user fail\r\n"); retval = -EFAULT; break; } break; } case EGIS_IOCTL_SET_CONTACTMODE_REG: { EgisMsg(dev->bPrintDbgMsg, KERN_INFO, "=ioctl=EGIS_IOCTL_SET_CONTACTMODE_REG "); if (copy_from_user(&dev->contactCBW, (void *)arg, CBW_SIZE)) { EgisMsg(dev->bPrintDbgMsg, KERN_ERR, "=ioctl=EGIS_IOCTL_SET_CONTACTMODE_REG copy from user fail\r\n"); retval = -EFAULT; break; } break; } /* -------------------- JADE USB BASIC XFER ----------------------- */ /* ---------------------------------------------------------------- */ case EGIS_IOCTL_BULK_READ: { retval = Egis_IO_Bulk_Read(dev, arg); break; } case EGIS_IOCTL_BULK_WRITE: { retval = Egis_IO_Bulk_Write(dev, arg); break; } case EGIS_IOCTL_CTRLXFER_READ: { retval = Egis_IO_CtrlXfer(dev, arg, Ctrl_IN); break; } case EGIS_IOCTL_CTRLXFER_WRITE: { retval = Egis_IO_CtrlXfer(dev, arg, Ctrl_OUT); break; } /*---------------------- Helper function ------------------------- */ /*---------------------------------------------------------------- */ case EGIS_IOCTL_ENTER_SUSPEND: dev->udev->autosuspend_delay = 0; break; case EGIS_IOCTL_RESET_DEVICE: retval = Egis_IO_Reset_Device(dev); break; case EGIS_IOCTL_CREATE_SIGNAL: dev->sig_type = arg; break; /* -------------------- Alternative Setting ----------------------- */ /* ---------------------------------------------------------------- */ case EGIS_IOCTL_SET_AUTOSUSPEND_TIME: dev->idle_delay_time = arg; dev->udev->autosuspend_delay = dev->idle_delay_time*HZ; EgisMsg(dev->bPrintDbgMsg, KERN_INFO, "=ioctl= idle-delay time %d \r\n", dev->idle_delay_time); break; /* ------------------------- Information -------------------------- */ /* ---------------------------------------------------------------- */ case EGIS_IOCTL_GET_VERSION: EgisMsg(dev->bPrintDbgMsg, KERN_INFO, "=ioctl= EGIS_IOCTL_GET_VERSION %s\r\n", dev->version.vstring); if (copy_to_user((void *)arg, &dev->version, sizeof(FPDriver_Version))) { EgisMsg(dev->bPrintDbgMsg, KERN_ERR, "=ioctl= EGIS_IOCTL_GET_VERSION copy to user fail\r\n"); retval = -EFAULT; break; } break; /* ------------------------ Debug usage --------------------------- */ /* ---------------------------------------------------------------- */ case EGIS_IOCTL_ENABLE_DBG_MSG: dev->bPrintDbgMsg = arg; break; /* ------------------------ FOR TEST ------------------------------ */ /* ---------------------------------------------------------------- */ case EGIS_IOCTL_TS_SIGNAL: if (dev->async_resume) { EgisMsg(dev->bPrintDbgMsg, KERN_INFO, "=ioctl= kill_fasync resume!!\r\n"); kill_fasync(&dev->async_resume, SIGIO, POLL_IN); } if (dev->async_suspend) { EgisMsg(dev->bPrintDbgMsg, KERN_INFO, "=ioctl= kill_fasync suspend !!\r\n"); kill_fasync(&dev->async_suspend, SIGIO, POLL_IN); } break; case EGIS_IOCTL_TS_SWITCH_AUTOSUSPEND: arg ? usb_enable_autosuspend(dev->udev):usb_disable_autosuspend(dev->udev); break; case EGIS_IOCTL_TS_SWITCH_RMWAKEUP: dev->udev->do_remote_wakeup = arg; EgisMsg(dev->bPrintDbgMsg, KERN_INFO, "=ioctl= do_remote_wakeup %d \r\n", dev->udev->do_remote_wakeup); break; default : retval = -ENOTTY; break; } } else { retval = -ENOTTY; } exit: /* ----- Auto suspend ----- */ usb_autopm_put_interface(dev->interface); mutex_unlock(&dev->io_mutex); printk(KERN_INFO "Patrick-> ss801u_ioctl finish\n"); return retval; }
/* * Receive a message with payloads from the USB bus into an skb * * @i2400mu: USB device descriptor * @rx_skb: skb where to place the received message * * Deals with all the USB-specifics of receiving, dynamically * increasing the buffer size if so needed. Returns the payload in the * skb, ready to process. On a zero-length packet, we retry. * * On soft USB errors, we retry (until they become too frequent and * then are promoted to hard); on hard USB errors, we reset the * device. On other errors (skb realloacation, we just drop it and * hope for the next invocation to solve it). * * Returns: pointer to the skb if ok, ERR_PTR on error. * NOTE: this function might realloc the skb (if it is too small), * so always update with the one returned. * ERR_PTR() is < 0 on error. * Will return NULL if it cannot reallocate -- this can be * considered a transient retryable error. */ static struct sk_buff *i2400mu_rx(struct i2400mu *i2400mu, struct sk_buff *rx_skb) { int result = 0; struct device *dev = &i2400mu->usb_iface->dev; int usb_pipe, read_size, rx_size, do_autopm; struct usb_endpoint_descriptor *epd; const size_t max_pkt_size = 512; d_fnstart(4, dev, "(i2400mu %p)\n", i2400mu); do_autopm = atomic_read(&i2400mu->do_autopm); result = do_autopm ? usb_autopm_get_interface(i2400mu->usb_iface) : 0; if (result < 0) { dev_err(dev, "RX: can't get autopm: %d\n", result); do_autopm = 0; } epd = usb_get_epd(i2400mu->usb_iface, i2400mu->endpoint_cfg.bulk_in); usb_pipe = usb_rcvbulkpipe(i2400mu->usb_dev, epd->bEndpointAddress); retry: rx_size = skb_end_pointer(rx_skb) - rx_skb->data - rx_skb->len; if (unlikely(rx_size % max_pkt_size == 0)) { rx_size -= 8; d_printf(1, dev, "RX: rx_size adapted to %d [-8]\n", rx_size); } result = usb_bulk_msg( i2400mu->usb_dev, usb_pipe, rx_skb->data + rx_skb->len, rx_size, &read_size, 200); usb_mark_last_busy(i2400mu->usb_dev); switch (result) { case 0: if (read_size == 0) goto retry; /* ZLP, just resubmit */ skb_put(rx_skb, read_size); break; case -EPIPE: /* * Stall -- maybe the device is choking with our * requests. Clear it and give it some time. If they * happen to often, it might be another symptom, so we * reset. * * No error handling for usb_clear_halt(0; if it * works, the retry works; if it fails, this switch * does the error handling for us. */ if (edc_inc(&i2400mu->urb_edc, 10 * EDC_MAX_ERRORS, EDC_ERROR_TIMEFRAME)) { dev_err(dev, "BM-CMD: too many stalls in " "URB; resetting device\n"); goto do_reset; } usb_clear_halt(i2400mu->usb_dev, usb_pipe); msleep(10); /* give the device some time */ goto retry; case -EINVAL: /* while removing driver */ case -ENODEV: /* dev disconnect ... */ case -ENOENT: /* just ignore it */ case -ESHUTDOWN: case -ECONNRESET: break; case -EOVERFLOW: { /* too small, reallocate */ struct sk_buff *new_skb; rx_size = i2400mu_rx_size_grow(i2400mu); if (rx_size <= (1 << 16)) /* cap it */ i2400mu->rx_size = rx_size; else if (printk_ratelimit()) { dev_err(dev, "BUG? rx_size up to %d\n", rx_size); result = -EINVAL; goto out; } skb_put(rx_skb, read_size); new_skb = skb_copy_expand(rx_skb, 0, rx_size - rx_skb->len, GFP_KERNEL); if (new_skb == NULL) { if (printk_ratelimit()) dev_err(dev, "RX: Can't reallocate skb to %d; " "RX dropped\n", rx_size); kfree_skb(rx_skb); rx_skb = NULL; goto out; /* drop it...*/ } kfree_skb(rx_skb); rx_skb = new_skb; i2400mu->rx_size_cnt = 0; i2400mu->rx_size_acc = i2400mu->rx_size; d_printf(1, dev, "RX: size changed to %d, received %d, " "copied %d, capacity %ld\n", rx_size, read_size, rx_skb->len, (long) (skb_end_pointer(new_skb) - new_skb->head)); goto retry; } /* In most cases, it happens due to the hardware scheduling a * read when there was no data - unfortunately, we have no way * to tell this timeout from a USB timeout. So we just ignore * it. */ case -ETIMEDOUT: dev_err(dev, "RX: timeout: %d\n", result); result = 0; break; default: /* Any error */ if (edc_inc(&i2400mu->urb_edc, EDC_MAX_ERRORS, EDC_ERROR_TIMEFRAME)) goto error_reset; dev_err(dev, "RX: error receiving URB: %d, retrying\n", result); goto retry; } out: if (do_autopm) usb_autopm_put_interface(i2400mu->usb_iface); d_fnend(4, dev, "(i2400mu %p) = %p\n", i2400mu, rx_skb); return rx_skb; error_reset: dev_err(dev, "RX: maximum errors in URB exceeded; " "resetting device\n"); do_reset: usb_queue_reset_device(i2400mu->usb_iface); rx_skb = ERR_PTR(result); goto out; }
/* * Sends a barker buffer to the device * * This helper will allocate a kmalloced buffer and use it to transmit * (then free it). Reason for this is that other arches cannot use * stack/vmalloc/text areas for DMA transfers. * * Error recovery here is simpler: anything is considered a hard error * and will move the reset code to use a last-resort bus-based reset. */ static int __i2400mu_send_barker(struct i2400mu *i2400mu, const __le32 *barker, size_t barker_size, unsigned endpoint) { struct usb_endpoint_descriptor *epd = NULL; int pipe, actual_len, ret; struct device *dev = &i2400mu->usb_iface->dev; void *buffer; int do_autopm = 1; ret = usb_autopm_get_interface(i2400mu->usb_iface); if (ret < 0) { dev_err(dev, "RESET: can't get autopm: %d\n", ret); do_autopm = 0; } ret = -ENOMEM; buffer = kmalloc(barker_size, GFP_KERNEL); if (buffer == NULL) goto error_kzalloc; epd = usb_get_epd(i2400mu->usb_iface, endpoint); pipe = usb_sndbulkpipe(i2400mu->usb_dev, epd->bEndpointAddress); memcpy(buffer, barker, barker_size); retry: ret = usb_bulk_msg(i2400mu->usb_dev, pipe, buffer, barker_size, &actual_len, 200); switch (ret) { case 0: if (actual_len != barker_size) { /* Too short? drop it */ dev_err(dev, "E: %s: short write (%d B vs %zu " "expected)\n", __func__, actual_len, barker_size); ret = -EIO; } break; case -EPIPE: /* * Stall -- maybe the device is choking with our * requests. Clear it and give it some time. If they * happen to often, it might be another symptom, so we * reset. * * No error handling for usb_clear_halt(0; if it * works, the retry works; if it fails, this switch * does the error handling for us. */ if (edc_inc(&i2400mu->urb_edc, 10 * EDC_MAX_ERRORS, EDC_ERROR_TIMEFRAME)) { dev_err(dev, "E: %s: too many stalls in " "URB; resetting device\n", __func__); usb_queue_reset_device(i2400mu->usb_iface); /* fallthrough */ } else { usb_clear_halt(i2400mu->usb_dev, pipe); msleep(10); /* give the device some time */ goto retry; } case -EINVAL: /* while removing driver */ case -ENODEV: /* dev disconnect ... */ case -ENOENT: /* just ignore it */ case -ESHUTDOWN: /* and exit */ case -ECONNRESET: ret = -ESHUTDOWN; break; default: /* Some error? */ if (edc_inc(&i2400mu->urb_edc, EDC_MAX_ERRORS, EDC_ERROR_TIMEFRAME)) { dev_err(dev, "E: %s: maximum errors in URB " "exceeded; resetting device\n", __func__); usb_queue_reset_device(i2400mu->usb_iface); } else { dev_warn(dev, "W: %s: cannot send URB: %d\n", __func__, ret); goto retry; } } kfree(buffer); error_kzalloc: if (do_autopm) usb_autopm_put_interface(i2400mu->usb_iface); return ret; }
/* Fill the buffer. Called with dev->lock held */ static int _chaoskey_fill(struct chaoskey *dev) { DEFINE_WAIT(wait); int result; bool started; usb_dbg(dev->interface, "fill"); /* Return immediately if someone called before the buffer was * empty */ if (dev->valid != dev->used) { usb_dbg(dev->interface, "not empty yet (valid %d used %d)", dev->valid, dev->used); return 0; } /* Bail if the device has been removed */ if (!dev->present) { usb_dbg(dev->interface, "device not present"); return -ENODEV; } /* Make sure the device is awake */ result = usb_autopm_get_interface(dev->interface); if (result) { usb_dbg(dev->interface, "wakeup failed (result %d)", result); return result; } dev->reading = true; result = usb_submit_urb(dev->urb, GFP_KERNEL); if (result < 0) { result = usb_translate_errors(result); dev->reading = false; goto out; } /* The first read on the Alea takes a little under 2 seconds. * Reads after the first read take only a few microseconds * though. Presumably the entropy-generating circuit needs * time to ramp up. So, we wait longer on the first read. */ started = dev->reads_started; dev->reads_started = true; result = wait_event_interruptible_timeout( dev->wait_q, !dev->reading, (started ? NAK_TIMEOUT : ALEA_FIRST_TIMEOUT) ); if (result < 0) goto out; if (result == 0) result = -ETIMEDOUT; else result = dev->valid; out: /* Let the device go back to sleep eventually */ usb_autopm_put_interface(dev->interface); usb_dbg(dev->interface, "read %d bytes", dev->valid); return result; }
static int __i2400mu_send_barker(struct i2400mu *i2400mu, const __le32 *barker, size_t barker_size, unsigned endpoint) { struct usb_endpoint_descriptor *epd = NULL; int pipe, actual_len, ret; struct device *dev = &i2400mu->usb_iface->dev; void *buffer; int do_autopm = 1; ret = usb_autopm_get_interface(i2400mu->usb_iface); if (ret < 0) { dev_err(dev, "RESET: can't get autopm: %d\n", ret); do_autopm = 0; } ret = -ENOMEM; buffer = kmalloc(barker_size, GFP_KERNEL); if (buffer == NULL) goto error_kzalloc; epd = usb_get_epd(i2400mu->usb_iface, endpoint); pipe = usb_sndbulkpipe(i2400mu->usb_dev, epd->bEndpointAddress); memcpy(buffer, barker, barker_size); retry: ret = usb_bulk_msg(i2400mu->usb_dev, pipe, buffer, barker_size, &actual_len, 200); switch (ret) { case 0: if (actual_len != barker_size) { dev_err(dev, "E: %s: short write (%d B vs %zu " "expected)\n", __func__, actual_len, barker_size); ret = -EIO; } break; case -EPIPE: if (edc_inc(&i2400mu->urb_edc, 10 * EDC_MAX_ERRORS, EDC_ERROR_TIMEFRAME)) { dev_err(dev, "E: %s: too many stalls in " "URB; resetting device\n", __func__); usb_queue_reset_device(i2400mu->usb_iface); } else { usb_clear_halt(i2400mu->usb_dev, pipe); msleep(10); goto retry; } case -EINVAL: case -ENODEV: case -ENOENT: case -ESHUTDOWN: case -ECONNRESET: ret = -ESHUTDOWN; break; default: if (edc_inc(&i2400mu->urb_edc, EDC_MAX_ERRORS, EDC_ERROR_TIMEFRAME)) { dev_err(dev, "E: %s: maximum errors in URB " "exceeded; resetting device\n", __func__); usb_queue_reset_device(i2400mu->usb_iface); } else { dev_warn(dev, "W: %s: cannot send URB: %d\n", __func__, ret); goto retry; } } kfree(buffer); error_kzalloc: if (do_autopm) usb_autopm_put_interface(i2400mu->usb_iface); return ret; }
static int rmnet_usb_ctrl_write(struct rmnet_ctrl_dev *dev, char *buf, size_t size) { int result; struct urb *sndurb; struct usb_ctrlrequest *out_ctlreq; struct usb_device *udev; #ifdef HTC_DEBUG_QMI_STUCK struct ctrl_write_context *context; #endif if (!is_dev_connected(dev)) return -ENETRESET; udev = interface_to_usbdev(dev->intf); sndurb = usb_alloc_urb(0, GFP_KERNEL); if (!sndurb) { dev_err(dev->devicep, "Error allocating read urb\n"); return -ENOMEM; } out_ctlreq = kmalloc(sizeof(*out_ctlreq), GFP_KERNEL); if (!out_ctlreq) { usb_free_urb(sndurb); dev_err(dev->devicep, "Error allocating setup packet buffer\n"); return -ENOMEM; } #ifdef HTC_DEBUG_QMI_STUCK context = kmalloc(sizeof(struct ctrl_write_context), GFP_KERNEL); if (!context) { kfree(out_ctlreq); usb_free_urb(sndurb); dev_err(dev->devicep, "Error allocating private data\n"); return -ENOMEM; } context->dev = dev; #endif out_ctlreq->bRequestType = (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE); out_ctlreq->bRequest = USB_CDC_SEND_ENCAPSULATED_COMMAND; out_ctlreq->wValue = 0; out_ctlreq->wIndex = dev->intf->cur_altsetting->desc.bInterfaceNumber; out_ctlreq->wLength = cpu_to_le16(size); usb_fill_control_urb(sndurb, udev, usb_sndctrlpipe(udev, 0), (unsigned char *)out_ctlreq, (void *)buf, size, #ifdef HTC_DEBUG_QMI_STUCK ctrl_write_callback, context); #else ctrl_write_callback, dev); #endif result = usb_autopm_get_interface(dev->intf); if (result < 0) { dev_err(dev->devicep, "%s: Unable to resume interface: %d\n", __func__, result); usb_free_urb(sndurb); kfree(out_ctlreq); #ifdef HTC_DEBUG_QMI_STUCK kfree(context); #endif return result; } #ifdef HTC_LOG_RMNET_USB_CTRL log_rmnet_usb_ctrl_event(dev->intf, "Tx", size); #endif #ifdef HTC_DEBUG_QMI_STUCK init_timer(&context->timer); context->timer.function = rmnet_usb_ctrl_write_timer_expire; context->timer.data = (unsigned long)sndurb; context->start_jiffies = jiffies; mod_timer(&context->timer, jiffies + msecs_to_jiffies(QMI_TX_NO_CB_TIMEOUT)); #endif usb_anchor_urb(sndurb, &dev->tx_submitted); dev->snd_encap_cmd_cnt++; result = usb_submit_urb(sndurb, GFP_KERNEL); if (result < 0) { dev_err(dev->devicep, "%s: Submit URB error %d\n", __func__, result); dev->snd_encap_cmd_cnt--; usb_autopm_put_interface(dev->intf); usb_unanchor_urb(sndurb); usb_free_urb(sndurb); kfree(out_ctlreq); #ifdef HTC_DEBUG_QMI_STUCK del_timer(&context->timer); kfree(context); #endif return result; } return size; }
int diag_bridge_write(char *data, int size) { struct urb *urb = NULL; unsigned int pipe; struct diag_bridge *dev = __dev; int ret; pr_debug("writing %d bytes", size); if (!dev || !dev->ifc) { pr_err("device is disconnected"); return -ENODEV; } if (!dev->ops) { pr_err("bridge is not open"); return -ENODEV; } if (!size) { dev_err(&dev->ifc->dev, "invalid size:%d\n", size); return -EINVAL; } /* if there was a previous unrecoverable error, just quit */ if (dev->err) return -ENODEV; kref_get(&dev->kref); urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) { dev_err(&dev->ifc->dev, "unable to allocate urb\n"); ret = -ENOMEM; goto error; } ret = usb_autopm_get_interface(dev->ifc); if (ret < 0 && ret != -EAGAIN && ret != -EACCES) { pr_err_ratelimited("write: autopm_get failed:%d", ret); goto free_error; } pipe = usb_sndbulkpipe(dev->udev, dev->out_epAddr); usb_fill_bulk_urb(urb, dev->udev, pipe, data, size, diag_bridge_write_cb, dev); urb->transfer_flags |= URB_ZERO_PACKET; usb_anchor_urb(urb, &dev->submitted); dev->pending_writes++; ret = usb_submit_urb(urb, GFP_KERNEL); if (ret) { pr_err_ratelimited("submitting urb failed err:%d", ret); dev->pending_writes--; usb_unanchor_urb(urb); usb_autopm_put_interface(dev->ifc); goto free_error; } free_error: usb_free_urb(urb); error: if (ret) /* otherwise this is done in the completion handler */ kref_put(&dev->kref, diag_bridge_delete); return ret; }
static ssize_t ss801u_read(struct file *file, char *buffer, size_t count, loff_t *ppos) { usb_ss801u *dev; int retval = 0; int bytes_read; char *kbuf; printk(KERN_INFO "Patrick-> ss801u_read start\n"); dev = (usb_ss801u *)file->private_data; mutex_lock(&dev->io_mutex); /*----- To NOT go to suspend ----- */ usb_autopm_get_interface(dev->interface); if (!dev->interface) { /* disconnect() was called */ retval = -ENODEV; goto exit; } /* --------------- CASE1 : only return driver version ----------------------- */ /* -------------------------------------------------------------------------- */ if (dev->bReadTwice) { dev->bReadTwice = false; goto exit; } kbuf = kzalloc(count, GFP_KERNEL); if (!kbuf) goto exit; sprintf(kbuf, "%s v%s\r\n", NAME_EGISDRIVER, dev->version.vstring); bytes_read = strlen(kbuf); if (copy_to_user(buffer, kbuf, bytes_read)) { retval = 0; } else { retval = count; ppos += bytes_read; dev->bReadTwice = true; } kfree(kbuf); /*/ //----------------------- CASE2 : bulk read --------------------------------// //----------------------- ---------------------------------------------------// //----- do a blocking bulk read to get data from the device -----/ retval = usb_bulk_msg( dev->udev, usb_rcvbulkpipe(dev->udev, dev->bulk_in_endpointAddr), dev->bulk_in_buffer, min(dev->bulk_in_size, count), &bytes_read, 10000 ); //----- if the read was successful, copy the data to userspace -----// if (!retval) { if (copy_to_user(buffer, dev->bulk_in_buffer , bytes_read)) retval = -EFAULT; else retval = bytes_read; } else { Egis_Reset_device(dev); EgisMsg(dev->bPrintDbgMsg, KERN_ERR, "=READ= fail %d\r\n", retval); } //*/ exit: /* ----- Auto suspend ----- */ usb_autopm_put_interface(dev->interface); mutex_unlock(&dev->io_mutex); EgisMsg(dev->bPrintDbgMsg, KERN_INFO, "READ bytes %d\r\n", retval); printk(KERN_INFO "Patrick-> ss801u_read finish\n"); return retval; }
static struct sk_buff *i2400mu_rx(struct i2400mu *i2400mu, struct sk_buff *rx_skb) { int result = 0; struct device *dev = &i2400mu->usb_iface->dev; int usb_pipe, read_size, rx_size, do_autopm; struct usb_endpoint_descriptor *epd; const size_t max_pkt_size = 512; d_fnstart(4, dev, "(i2400mu %p)\n", i2400mu); do_autopm = atomic_read(&i2400mu->do_autopm); result = do_autopm ? usb_autopm_get_interface(i2400mu->usb_iface) : 0; if (result < 0) { dev_err(dev, "RX: can't get autopm: %d\n", result); do_autopm = 0; } epd = usb_get_epd(i2400mu->usb_iface, i2400mu->endpoint_cfg.bulk_in); usb_pipe = usb_rcvbulkpipe(i2400mu->usb_dev, epd->bEndpointAddress); retry: rx_size = skb_end_pointer(rx_skb) - rx_skb->data - rx_skb->len; if (unlikely(rx_size % max_pkt_size == 0)) { rx_size -= 8; d_printf(1, dev, "RX: rx_size adapted to %d [-8]\n", rx_size); } result = usb_bulk_msg( i2400mu->usb_dev, usb_pipe, rx_skb->data + rx_skb->len, rx_size, &read_size, 200); usb_mark_last_busy(i2400mu->usb_dev); switch (result) { case 0: if (read_size == 0) goto retry; /* */ skb_put(rx_skb, read_size); break; case -EPIPE: /* */ if (edc_inc(&i2400mu->urb_edc, 10 * EDC_MAX_ERRORS, EDC_ERROR_TIMEFRAME)) { dev_err(dev, "BM-CMD: too many stalls in " "URB; resetting device\n"); goto do_reset; } usb_clear_halt(i2400mu->usb_dev, usb_pipe); msleep(10); /* */ goto retry; case -EINVAL: /* */ case -ENODEV: /* */ case -ENOENT: /* */ case -ESHUTDOWN: case -ECONNRESET: break; case -EOVERFLOW: { /* */ struct sk_buff *new_skb; rx_size = i2400mu_rx_size_grow(i2400mu); if (rx_size <= (1 << 16)) /* */ i2400mu->rx_size = rx_size; else if (printk_ratelimit()) { dev_err(dev, "BUG? rx_size up to %d\n", rx_size); result = -EINVAL; goto out; } skb_put(rx_skb, read_size); new_skb = skb_copy_expand(rx_skb, 0, rx_size - rx_skb->len, GFP_KERNEL); if (new_skb == NULL) { if (printk_ratelimit()) dev_err(dev, "RX: Can't reallocate skb to %d; " "RX dropped\n", rx_size); kfree_skb(rx_skb); rx_skb = NULL; goto out; /* */ } kfree_skb(rx_skb); rx_skb = new_skb; i2400mu->rx_size_cnt = 0; i2400mu->rx_size_acc = i2400mu->rx_size; d_printf(1, dev, "RX: size changed to %d, received %d, " "copied %d, capacity %ld\n", rx_size, read_size, rx_skb->len, (long) (skb_end_pointer(new_skb) - new_skb->head)); goto retry; } /* */ case -ETIMEDOUT: dev_err(dev, "RX: timeout: %d\n", result); result = 0; break; default: /* */ if (edc_inc(&i2400mu->urb_edc, EDC_MAX_ERRORS, EDC_ERROR_TIMEFRAME)) goto error_reset; dev_err(dev, "RX: error receiving URB: %d, retrying\n", result); goto retry; } out: if (do_autopm) usb_autopm_put_interface(i2400mu->usb_iface); d_fnend(4, dev, "(i2400mu %p) = %p\n", i2400mu, rx_skb); return rx_skb; error_reset: dev_err(dev, "RX: maximum errors in URB exceeded; " "resetting device\n"); do_reset: usb_queue_reset_device(i2400mu->usb_iface); rx_skb = ERR_PTR(result); goto out; }
static ssize_t wdm_write (struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { u8 *buf; int rv = -EMSGSIZE, r, we; struct wdm_device *desc = file->private_data; struct usb_ctrlrequest *req; if (count > desc->wMaxCommand) count = desc->wMaxCommand; spin_lock_irq(&desc->iuspin); we = desc->werr; desc->werr = 0; spin_unlock_irq(&desc->iuspin); if (we < 0) return -EIO; buf = kmalloc(count, GFP_KERNEL); if (!buf) { rv = -ENOMEM; goto outnl; } r = copy_from_user(buf, buffer, count); if (r > 0) { kfree(buf); rv = -EFAULT; goto outnl; } /* concurrent writes and disconnect */ r = mutex_lock_interruptible(&desc->wlock); rv = -ERESTARTSYS; if (r) { kfree(buf); goto outnl; } if (test_bit(WDM_DISCONNECTING, &desc->flags)) { kfree(buf); rv = -ENODEV; goto outnp; } r = usb_autopm_get_interface(desc->intf); if (r < 0) { kfree(buf); goto outnp; } if (!(file->f_flags & O_NONBLOCK)) r = wait_event_interruptible(desc->wait, !test_bit(WDM_IN_USE, &desc->flags)); else if (test_bit(WDM_IN_USE, &desc->flags)) r = -EAGAIN; if (r < 0) { kfree(buf); goto out; } req = desc->orq; usb_fill_control_urb( desc->command, interface_to_usbdev(desc->intf), /* using common endpoint 0 */ usb_sndctrlpipe(interface_to_usbdev(desc->intf), 0), (unsigned char *)req, buf, count, wdm_out_callback, desc ); req->bRequestType = (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE); req->bRequest = USB_CDC_SEND_ENCAPSULATED_COMMAND; req->wValue = 0; req->wIndex = desc->inum; req->wLength = cpu_to_le16(count); set_bit(WDM_IN_USE, &desc->flags); desc->outbuf = buf; rv = usb_submit_urb(desc->command, GFP_KERNEL); if (rv < 0) { kfree(buf); desc->outbuf = NULL; clear_bit(WDM_IN_USE, &desc->flags); dev_err(&desc->intf->dev, "Tx URB error: %d\n", rv); } else { dev_dbg(&desc->intf->dev, "Tx URB has been submitted index=%d", req->wIndex); } out: usb_autopm_put_interface(desc->intf); outnp: mutex_unlock(&desc->wlock); outnl: return rv < 0 ? rv : count; }
/* work that cannot be done in interrupt context uses keventd. * * NOTE: with 2.5 we could do more of this using completion callbacks, * especially now that control transfers can be queued. */ static void kevent (struct work_struct *work) { struct usbnet *dev = container_of(work, struct usbnet, kevent); int status; /* usb_clear_halt() needs a thread context */ if (test_bit (EVENT_TX_HALT, &dev->flags)) { unlink_urbs (dev, &dev->txq); status = usb_autopm_get_interface(dev->intf); if (status < 0) goto fail_pipe; status = usb_clear_halt (dev->udev, dev->out); usb_autopm_put_interface(dev->intf); if (status < 0 && status != -EPIPE && status != -ESHUTDOWN) { if (netif_msg_tx_err (dev)) fail_pipe: netdev_err(dev->net, "can't clear tx halt, status %d\n", status); } else { clear_bit (EVENT_TX_HALT, &dev->flags); if (status != -ESHUTDOWN) netif_wake_queue (dev->net); } } if (test_bit (EVENT_RX_HALT, &dev->flags)) { unlink_urbs (dev, &dev->rxq); status = usb_autopm_get_interface(dev->intf); if (status < 0) goto fail_halt; status = usb_clear_halt (dev->udev, dev->in); usb_autopm_put_interface(dev->intf); if (status < 0 && status != -EPIPE && status != -ESHUTDOWN) { if (netif_msg_rx_err (dev)) fail_halt: netdev_err(dev->net, "can't clear rx halt, status %d\n", status); } else { clear_bit (EVENT_RX_HALT, &dev->flags); tasklet_schedule (&dev->bh); } } /* tasklet could resubmit itself forever if memory is tight */ if (test_bit (EVENT_RX_MEMORY, &dev->flags)) { struct urb *urb = NULL; int resched = 1; if (netif_running (dev->net)) urb = usb_alloc_urb (0, GFP_KERNEL); else clear_bit (EVENT_RX_MEMORY, &dev->flags); if (urb != NULL) { clear_bit (EVENT_RX_MEMORY, &dev->flags); status = usb_autopm_get_interface(dev->intf); if (status < 0) { usb_free_urb(urb); goto fail_lowmem; } if (rx_submit (dev, urb, GFP_KERNEL) == -ENOLINK) resched = 0; usb_autopm_put_interface(dev->intf); fail_lowmem: if (resched) tasklet_schedule (&dev->bh); } } if (test_bit (EVENT_LINK_RESET, &dev->flags)) { struct driver_info *info = dev->driver_info; int retval = 0; clear_bit (EVENT_LINK_RESET, &dev->flags); status = usb_autopm_get_interface(dev->intf); if (status < 0) goto skip_reset; if(info->link_reset && (retval = info->link_reset(dev)) < 0) { usb_autopm_put_interface(dev->intf); skip_reset: netdev_info(dev->net, "link reset failed (%d) usbnet usb-%s-%s, %s\n", retval, dev->udev->bus->bus_name, dev->udev->devpath, info->description); } else { usb_autopm_put_interface(dev->intf); } } if (dev->flags) netdev_dbg(dev->net, "kevent done, flags = 0x%lx\n", dev->flags); }
int diag_bridge_read(char *data, int size) { struct urb *urb = NULL; unsigned int pipe; struct diag_bridge *dev = __dev; int ret; if (!dev) { printk(KERN_WARNING "[DIAG BRIDGE]%s dev is NULL\n",__func__); return -ENODEV; } pr_debug("reading %d bytes", size); if (!dev || !dev->ifc) { pr_err("device is disconnected"); return -ENODEV; } if (!dev->ops) { pr_err("bridge is not open"); return -ENODEV; } if (!size) { dev_err(&dev->udev->dev, "invalid size:%d\n", size); return -EINVAL; } /* if there was a previous unrecoverable error, just quit */ if (dev->err) { pr_info("diag_bridge_read:dev->err\n"); return -ENODEV; } kref_get(&dev->kref); urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) { dev_err(&dev->udev->dev, "unable to allocate urb\n"); ret = -ENOMEM; goto error; } ret = usb_autopm_get_interface(dev->ifc); if (ret < 0 && ret != -EAGAIN && ret != -EACCES) { pr_err_ratelimited("read: autopm_get failed:%d", ret); goto free_error; } pipe = usb_rcvbulkpipe(dev->udev, dev->in_epAddr); usb_fill_bulk_urb(urb, dev->udev, pipe, data, size, diag_bridge_read_cb, dev); usb_anchor_urb(urb, &dev->submitted); dev->pending_reads++; ret = usb_submit_urb(urb, GFP_KERNEL); if (ret) { pr_err_ratelimited("submitting urb failed err:%d", ret); dev->pending_reads--; usb_unanchor_urb(urb); } usb_autopm_put_interface(dev->ifc); free_error: usb_free_urb(urb); error: if (ret) /* otherwise this is done in the completion handler */ kref_put(&dev->kref, diag_bridge_delete); return ret; }
int usbnet_open (struct net_device *net) { struct usbnet *dev = netdev_priv(net); int retval; struct driver_info *info = dev->driver_info; if ((retval = usb_autopm_get_interface(dev->intf)) < 0) { netif_info(dev, ifup, dev->net, "resumption fail (%d) usbnet usb-%s-%s, %s\n", retval, dev->udev->bus->bus_name, dev->udev->devpath, info->description); goto done_nopm; } // put into "known safe" state if (info->reset && (retval = info->reset (dev)) < 0) { netif_info(dev, ifup, dev->net, "open reset fail (%d) usbnet usb-%s-%s, %s\n", retval, dev->udev->bus->bus_name, dev->udev->devpath, info->description); goto done; } // insist peer be connected if (info->check_connect && (retval = info->check_connect (dev)) < 0) { netif_dbg(dev, ifup, dev->net, "can't open; %d\n", retval); goto done; } /* start any status interrupt transfer */ if (dev->interrupt) { retval = usb_submit_urb (dev->interrupt, GFP_KERNEL); if (retval < 0) { netif_err(dev, ifup, dev->net, "intr submit %d\n", retval); goto done; } } set_bit(EVENT_DEV_OPEN, &dev->flags); netif_start_queue (net); netif_info(dev, ifup, dev->net, "open: enable queueing (rx %d, tx %d) mtu %d %s framing\n", (int)RX_QLEN(dev), (int)TX_QLEN(dev), dev->net->mtu, (dev->driver_info->flags & FLAG_FRAMING_NC) ? "NetChip" : (dev->driver_info->flags & FLAG_FRAMING_GL) ? "GeneSys" : (dev->driver_info->flags & FLAG_FRAMING_Z) ? "Zaurus" : (dev->driver_info->flags & FLAG_FRAMING_RN) ? "RNDIS" : (dev->driver_info->flags & FLAG_FRAMING_AX) ? "ASIX" : "simple"); // delay posting reads until we're fully open tasklet_schedule (&dev->bh); if (info->manage_power) { retval = info->manage_power(dev, 1); if (retval < 0) goto done; usb_autopm_put_interface(dev->intf); } return retval; done: usb_autopm_put_interface(dev->intf); done_nopm: return retval; }
int diag_bridge_read(char *data, int size) { struct urb *urb = NULL; unsigned int pipe; struct diag_bridge *dev = __dev; int ret; int spin = 50; struct usb_device *udev; if (!dev || !dev->udev) return -ENODEV; if (!size) { dev_err(&dev->udev->dev, "invalid size:%d\n", size); return -EINVAL; } if (!dev->ifc) { dev_err(&dev->udev->dev, "device is disconnected\n"); return -ENODEV; } /* if there was a previous unrecoverable error, just quit */ if (dev->err) return -ESHUTDOWN; while (check_request_blocked(rmnet_pm_dev) && spin--) { pr_debug("%s: wake up wait loop\n", __func__); msleep(20); } if (check_request_blocked(rmnet_pm_dev)) { pr_err("%s: in lpa wakeup, return EAGAIN\n", __func__); return -EAGAIN; } urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) { dev_err(&dev->udev->dev, "unable to allocate urb\n"); return -ENOMEM; } udev = interface_to_usbdev(dev->ifc); /* if dev handling suspend wait for suspended or active*/ if (pm_dev_runtime_get_enabled(udev) < 0) { usb_free_urb(urb); return -EAGAIN; } ret = usb_autopm_get_interface(dev->ifc); if (ret < 0) { dev_err(&dev->udev->dev, "autopm_get failed:%d\n", ret); usb_free_urb(urb); return ret; } pipe = usb_rcvbulkpipe(dev->udev, dev->in_epAddr); usb_fill_bulk_urb(urb, dev->udev, pipe, data, size, diag_bridge_read_cb, dev); usb_anchor_urb(urb, &dev->submitted); dev->pending_reads++; ret = usb_submit_urb(urb, GFP_KERNEL); if (ret) { dev_err(&dev->udev->dev, "submitting urb failed err:%d\n", ret); dev->pending_reads--; usb_unanchor_urb(urb); usb_free_urb(urb); usb_autopm_put_interface(dev->ifc); return ret; } usb_autopm_put_interface(dev->ifc); usb_free_urb(urb); return 0; }
int diag_bridge_write(char *data, int size) { struct urb *urb = NULL; unsigned int pipe; struct diag_bridge *dev = __dev; struct usb_device *udev; int ret; int spin; if (!dev || !dev->udev) return -ENODEV; if (!size) { dev_err(&dev->udev->dev, "invalid size:%d\n", size); return -EINVAL; } if (!dev->ifc) { dev_err(&dev->udev->dev, "device is disconnected\n"); return -ENODEV; } /* if there was a previous unrecoverable error, just quit */ if (dev->err) return -ESHUTDOWN; spin = 50; while (check_request_blocked(rmnet_pm_dev) && spin--) { pr_info("%s: wake up wait loop\n", __func__); msleep(20); } if (check_request_blocked(rmnet_pm_dev)) { pr_err("%s: in lpa wakeup, return EAGAIN\n", __func__); return -EAGAIN; } urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) { err("unable to allocate urb"); return -ENOMEM; } udev = interface_to_usbdev(dev->ifc); /* if dev handling suspend wait for suspended or active*/ if (pm_dev_runtime_get_enabled(udev) < 0) { usb_free_urb(urb); return -EAGAIN; } ret = usb_autopm_get_interface(dev->ifc); if (ret < 0) { dev_err(&dev->udev->dev, "autopm_get failed:%d\n", ret); usb_free_urb(urb); return ret; } if (size == 4 || size == 5) { if (data[0] == 0x1d && data[1] == 0x1c && data[2] == 0x3b) pr_info("%s: diag.cfg [send start]\n", __func__); else if (data[0] == 0x60 && data[1] == 0x00 && data[2] == 0x12 && data[3] == 0x6a) pr_info("%s: diag.cfg [send complete]\n", __func__); } pipe = usb_sndbulkpipe(dev->udev, dev->out_epAddr); usb_fill_bulk_urb(urb, dev->udev, pipe, data, size, diag_bridge_write_cb, dev); usb_anchor_urb(urb, &dev->submitted); dev->pending_writes++; ret = usb_submit_urb(urb, GFP_KERNEL); if (ret) { dev_err(&dev->udev->dev, "submitting urb failed err:%d\n", ret); dev->pending_writes--; usb_unanchor_urb(urb); usb_free_urb(urb); usb_autopm_put_interface(dev->ifc); return ret; } #if 0 usb_free_urb(urb); #endif return 0; }
static int rmnet_usb_ctrl_write(struct rmnet_ctrl_dev *dev, char *buf, size_t size) { int result; struct urb *sndurb; struct usb_ctrlrequest *out_ctlreq; struct usb_device *udev; if (!is_dev_connected(dev)) return -ENETRESET; udev = interface_to_usbdev(dev->intf); usb_mark_last_busy(udev); sndurb = usb_alloc_urb(0, GFP_KERNEL); if (!sndurb) { dev_err(dev->devicep, "Error allocating read urb\n"); return -ENOMEM; } out_ctlreq = kmalloc(sizeof(*out_ctlreq), GFP_KERNEL); if (!out_ctlreq) { kfree(buf); usb_free_urb(sndurb); dev_err(dev->devicep, "Error allocating setup packet buffer\n"); return -ENOMEM; } /* CDC Send Encapsulated Request packet */ out_ctlreq->bRequestType = (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE); out_ctlreq->bRequest = USB_CDC_SEND_ENCAPSULATED_COMMAND; out_ctlreq->wValue = 0; out_ctlreq->wIndex = dev->intf->cur_altsetting->desc.bInterfaceNumber; out_ctlreq->wLength = cpu_to_le16(size); usb_fill_control_urb(sndurb, udev, usb_sndctrlpipe(udev, 0), (unsigned char *)out_ctlreq, (void *)buf, size, ctrl_write_callback, dev); result = usb_autopm_get_interface(dev->intf); if (result < 0) { dev_err(dev->devicep, "%s: Unable to resume interface: %d\n", __func__, result); /* * Revisit: if (result == -EPERM) * rmnet_usb_suspend(dev->intf, PMSG_SUSPEND); */ kfree(buf); usb_free_urb(sndurb); kfree(out_ctlreq); return result; } usb_anchor_urb(sndurb, &dev->tx_submitted); dev->snd_encap_cmd_cnt++; usb_mark_last_busy(udev); result = usb_submit_urb(sndurb, GFP_KERNEL); if (result < 0) { dev_err(dev->devicep, "%s: Submit URB error %d\n", __func__, result); dev->snd_encap_cmd_cnt--; usb_autopm_put_interface(dev->intf); usb_unanchor_urb(sndurb); kfree(buf); usb_free_urb(sndurb); kfree(out_ctlreq); return result; } return size; }