static int us122l_create_usbmidi(struct snd_card *card) { static struct snd_usb_midi_endpoint_info quirk_data = { .out_ep = 4, .in_ep = 3, .out_cables = 0x001, .in_cables = 0x001 }; static struct snd_usb_audio_quirk quirk = { .vendor_name = "US122L", .product_name = NAME_ALLCAPS, .ifnum = 1, .type = QUIRK_MIDI_US122L, .data = &quirk_data }; struct usb_device *dev = US122L(card)->dev; struct usb_interface *iface = usb_ifnum_to_if(dev, 1); return snd_usbmidi_create(card, iface, &US122L(card)->midi_list, &quirk); } static int us144_create_usbmidi(struct snd_card *card) { static struct snd_usb_midi_endpoint_info quirk_data = { .out_ep = 4, .in_ep = 3, .out_cables = 0x001, .in_cables = 0x001 }; static struct snd_usb_audio_quirk quirk = { .vendor_name = "US144", .product_name = NAME_ALLCAPS, .ifnum = 0, .type = QUIRK_MIDI_US122L, .data = &quirk_data }; struct usb_device *dev = US122L(card)->dev; struct usb_interface *iface = usb_ifnum_to_if(dev, 0); return snd_usbmidi_create(card, iface, &US122L(card)->midi_list, &quirk); } /* * Wrapper for usb_control_msg(). * Allocates a temp buffer to prevent dmaing from/to the stack. */ static int us122l_ctl_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype, __u16 value, __u16 index, void *data, __u16 size, int timeout) { int err; void *buf = NULL; if (size > 0) { buf = kmemdup(data, size, GFP_KERNEL); if (!buf) return -ENOMEM; } err = usb_control_msg(dev, pipe, request, requesttype, value, index, buf, size, timeout); if (size > 0) { memcpy(data, buf, size); kfree(buf); } return err; } static void pt_info_set(struct usb_device *dev, u8 v) { int ret; ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 'I', USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, v, 0, NULL, 0, 1000); snd_printdd(KERN_DEBUG "%i\n", ret); } static void usb_stream_hwdep_vm_open(struct vm_area_struct *area) { struct us122l *us122l = area->vm_private_data; atomic_inc(&us122l->mmap_count); snd_printdd(KERN_DEBUG "%i\n", atomic_read(&us122l->mmap_count)); } static int usb_stream_hwdep_vm_fault(struct vm_area_struct *area, struct vm_fault *vmf) { unsigned long offset; struct page *page; void *vaddr; struct us122l *us122l = area->vm_private_data; struct usb_stream *s; mutex_lock(&us122l->mutex); s = us122l->sk.s; if (!s) goto unlock; offset = vmf->pgoff << PAGE_SHIFT; if (offset < PAGE_ALIGN(s->read_size)) vaddr = (char *)s + offset; else { offset -= PAGE_ALIGN(s->read_size); if (offset >= PAGE_ALIGN(s->write_size)) goto unlock; vaddr = us122l->sk.write_page + offset; } page = virt_to_page(vaddr); get_page(page); mutex_unlock(&us122l->mutex); vmf->page = page; return 0; unlock: mutex_unlock(&us122l->mutex); return VM_FAULT_SIGBUS; } static void usb_stream_hwdep_vm_close(struct vm_area_struct *area) { struct us122l *us122l = area->vm_private_data; atomic_dec(&us122l->mmap_count); snd_printdd(KERN_DEBUG "%i\n", atomic_read(&us122l->mmap_count)); } static const struct vm_operations_struct usb_stream_hwdep_vm_ops = { .open = usb_stream_hwdep_vm_open, .fault = usb_stream_hwdep_vm_fault, .close = usb_stream_hwdep_vm_close, }; static int usb_stream_hwdep_open(struct snd_hwdep *hw, struct file *file) { struct us122l *us122l = hw->private_data; struct usb_interface *iface; snd_printdd(KERN_DEBUG "%p %p\n", hw, file); if (hw->used >= 2) return -EBUSY; if (!us122l->first) us122l->first = file; if (us122l->dev->descriptor.idProduct == USB_ID_US144 || us122l->dev->descriptor.idProduct == USB_ID_US144MKII) { iface = usb_ifnum_to_if(us122l->dev, 0); usb_autopm_get_interface(iface); } iface = usb_ifnum_to_if(us122l->dev, 1); usb_autopm_get_interface(iface); return 0; } static int usb_stream_hwdep_release(struct snd_hwdep *hw, struct file *file) { struct us122l *us122l = hw->private_data; struct usb_interface *iface; snd_printdd(KERN_DEBUG "%p %p\n", hw, file); if (us122l->dev->descriptor.idProduct == USB_ID_US144 || us122l->dev->descriptor.idProduct == USB_ID_US144MKII) { iface = usb_ifnum_to_if(us122l->dev, 0); usb_autopm_put_interface(iface); } iface = usb_ifnum_to_if(us122l->dev, 1); usb_autopm_put_interface(iface); if (us122l->first == file) us122l->first = NULL; mutex_lock(&us122l->mutex); if (us122l->master == file) us122l->master = us122l->slave; us122l->slave = NULL; mutex_unlock(&us122l->mutex); return 0; } static int usb_stream_hwdep_mmap(struct snd_hwdep *hw, struct file *filp, struct vm_area_struct *area) { unsigned long size = area->vm_end - area->vm_start; struct us122l *us122l = hw->private_data; unsigned long offset; struct usb_stream *s; int err = 0; bool read; offset = area->vm_pgoff << PAGE_SHIFT; mutex_lock(&us122l->mutex); s = us122l->sk.s; read = offset < s->read_size; if (read && area->vm_flags & VM_WRITE) { err = -EPERM; goto out; } snd_printdd(KERN_DEBUG "%lu %u\n", size, read ? s->read_size : s->write_size); /* if userspace tries to mmap beyond end of our buffer, fail */ if (size > PAGE_ALIGN(read ? s->read_size : s->write_size)) { snd_printk(KERN_WARNING "%lu > %u\n", size, read ? s->read_size : s->write_size); err = -EINVAL; goto out; } area->vm_ops = &usb_stream_hwdep_vm_ops; area->vm_flags |= VM_RESERVED; area->vm_private_data = us122l; atomic_inc(&us122l->mmap_count); out: mutex_unlock(&us122l->mutex); return err; }
static int acm_tty_open(struct tty_struct *tty, struct file *filp) { struct acm *acm; int rv = -EINVAL; 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; acm->tty = tty; /* force low_latency on so that our tty_push actually forces the data through, otherwise it is scheduled, and with high data rates data can get lost. */ tty->low_latency = 1; if (usb_autopm_get_interface(acm->control) < 0) goto early_bail; else acm->control->needs_remote_wakeup = 1; mutex_lock(&acm->mutex); if (acm->used++) { 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; 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->used--; mutex_unlock(&acm->mutex); early_bail: mutex_unlock(&open_mutex); return -EIO; }
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; /* * 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: 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; }
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 queue_work(usbnet_wq, &dev->bh_w); 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; }
/* * 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; }
int rtusb_fast_probe(VOID *handle, VOID **ppAd, struct usb_interface *intf) { VOID *pAd = *ppAd; VOID *pCookie = NULL; struct net_device *net_dev; #if (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) UCHAR WOWRun; #endif /* (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) */ #ifdef USB_SUPPORT_SELECTIVE_SUSPEND INT pm_usage_cnt; #endif /* USB_SUPPORT_SELECTIVE_SUSPEND */ struct usb_device *usb_dev = NULL; pCookie = RTMPCheckOsCookie(handle, &pAd); if (pCookie == NULL) return NDIS_STATUS_FAILURE; usb_dev = ((POS_COOKIE)pCookie)->pUsb_Dev; if (USBDevConfigInit(usb_dev, intf, pAd) == FALSE) { RTMPFreeAdapter(pAd); return NDIS_STATUS_FAILURE; } RTMP_DRIVER_USB_INIT(pAd, usb_dev, 0); /* netdevice-related structure set-up */ netdev_sysfs_reinit(&pAd, usb_dev); if (RTMP_DRIVER_IOCTL_SANITY_CHECK(pAd, NULL) != NDIS_STATUS_SUCCESS) { DBGPRINT(RT_DEBUG_ERROR, ("Driver is not init, ignore %s\n", __func__)); return NDIS_STATUS_SUCCESS; } #ifdef USB_SUPPORT_SELECTIVE_SUSPEND #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) pm_usage_cnt = atomic_read(&intf->pm_usage_cnt); #else pm_usage_cnt = intf->pm_usage_cnt; #endif if(pm_usage_cnt <= 0) usb_autopm_get_interface(intf); RTMP_DRIVER_ADAPTER_RT28XX_CMD_RADIO_ON(pAd); DBGPRINT(RT_DEBUG_ERROR, ("%s(): <=autosuspend\n", __func__)); return NDIS_STATUS_SUCCESS; #endif /* USB_SUPPORT_SELECTIVE_SUSPEND */ #if (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) RTMP_DRIVER_ADAPTER_RT28XX_WOW_RUNSTATUS(pAd, &WOWRun); if (WOWRun) RTMP_DRIVER_ADAPTER_RT28XX_WOW_DISABLE(pAd); else #endif /* (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) */ { DBGPRINT(RT_DEBUG_ERROR, ("%s :radio_on \n", __func__)); RTMP_DRIVER_ADAPTER_RT28XX_CMD_RADIO_ON(pAd); RTMP_DRIVER_NET_DEV_GET(pAd, &net_dev); netif_device_attach(net_dev); netif_start_queue(net_dev); netif_carrier_on(net_dev); netif_wake_queue(net_dev); } RTMP_DRIVER_USB_RESUME(pAd); DBGPRINT(RT_DEBUG_TRACE, ("<=%s()\n", __func__)); return NDIS_STATUS_SUCCESS; }
static int rtusb_resume(struct usb_interface *intf) { struct net_device *net_dev; #if (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) UCHAR WOWRun; #endif /* (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) */ #ifdef USB_SUPPORT_SELECTIVE_SUSPEND INT pm_usage_cnt; UCHAR Flag; #endif /* USB_SUPPORT_SELECTIVE_SUSPEND */ VOID *pAd = usb_get_intfdata(intf); DBGPRINT(RT_DEBUG_TRACE, ("%s()=>\n", __func__)); if (!RTMP_TEST_FLAG((PRTMP_ADAPTER)pAd, fRTMP_ADAPTER_START_UP)) return 0; #ifdef RESUME_WITH_USB_RESET_SUPPORT if (last_pm_cnt != os_get_sync_anchor()) { DBGPRINT(RT_DEBUG_ERROR, ("real suspend before\n")); return 0; } #endif /* RESUME_WITH_USB_RESET_SUPPORT */ #ifdef USB_SUPPORT_SELECTIVE_SUSPEND #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) pm_usage_cnt = atomic_read(&intf->pm_usage_cnt); #else pm_usage_cnt = intf->pm_usage_cnt; #endif if(pm_usage_cnt <= 0) usb_autopm_get_interface(intf); RTMP_DRIVER_ADAPTER_RT28XX_CMD_RADIO_ON(pAd); DBGPRINT(RT_DEBUG_ERROR, ("%s():=>autosuspend\n", __func__)); return 0; #endif /* USB_SUPPORT_SELECTIVE_SUSPEND */ #if (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) RTMP_DRIVER_ADAPTER_RT28XX_WOW_RUNSTATUS(pAd, &WOWRun); if (WOWRun) RTMP_DRIVER_ADAPTER_RT28XX_WOW_DISABLE(pAd); else #endif /* (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) */ { DBGPRINT(RT_DEBUG_ERROR, ("%s :radio_on \n", __func__)); RTMP_DRIVER_ADAPTER_RT28XX_CMD_RADIO_ON(pAd); RTMP_DRIVER_NET_DEV_GET(pAd, &net_dev); netif_device_attach(net_dev); netif_start_queue(net_dev); netif_carrier_on(net_dev); netif_wake_queue(net_dev); } RTMP_DRIVER_USB_RESUME(pAd); DBGPRINT(RT_DEBUG_TRACE, ("<=%s()\n", __func__)); return 0; }
int data_bridge_write(unsigned int id, struct sk_buff *skb) { int result; int size = skb->len; int pending; struct urb *txurb; struct data_bridge *dev = __dev[id]; struct bridge *brdg; if (!dev || !dev->brdg || !usb_get_intfdata(dev->intf)) return -ENODEV; brdg = dev->brdg; 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 */ *((struct data_bridge **)skb->cb) = dev; 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); 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; }
static int rt2870_probe( IN struct usb_interface *intf, IN struct usb_device *usb_dev, IN const USB_DEVICE_ID *dev_id, IN VOID **ppAd) { struct net_device *net_dev = NULL; VOID *pAd = (VOID *) NULL; int status, rv; PVOID handle; RTMP_OS_NETDEV_OP_HOOK netDevHook; ULONG OpMode; #ifdef CONFIG_PM #ifdef USB_SUPPORT_SELECTIVE_SUSPEND /* int pm_usage_cnt; */ int res =1 ; #endif /* USB_SUPPORT_SELECTIVE_SUSPEND */ #endif /* CONFIG_PM */ DBGPRINT(RT_DEBUG_TRACE, ("===>rt2870_probe()!\n")); #ifdef CONFIG_PM #ifdef USB_SUPPORT_SELECTIVE_SUSPEND res = usb_autopm_get_interface(intf); if (res) { DBGPRINT(RT_DEBUG_ERROR, ("rt2870_probe autopm_resume fail ------\n")); return -EIO; } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) atomic_set(&intf->pm_usage_cnt, 1); printk(" rt2870_probe ====> pm_usage_cnt %d \n", atomic_read(&intf->pm_usage_cnt)); #else intf->pm_usage_cnt = 1; printk(" rt2870_probe ====> pm_usage_cnt %d \n", intf->pm_usage_cnt); #endif #endif /* USB_SUPPORT_SELECTIVE_SUSPEND */ #endif /* CONFIG_PM */ /*RtmpDevInit============================================= */ /* Allocate RTMP_ADAPTER adapter structure */ /* handle = kmalloc(sizeof(struct os_cookie), GFP_KERNEL); */ os_alloc_mem(NULL, (UCHAR **)&handle, sizeof(struct os_cookie)); if (handle == NULL) { printk("rt2870_probe(): Allocate memory for os handle failed!\n"); return -ENOMEM; } memset(handle, 0, sizeof(struct os_cookie)); ((POS_COOKIE)handle)->pUsb_Dev = usb_dev; #ifdef CONFIG_PM #ifdef USB_SUPPORT_SELECTIVE_SUSPEND ((POS_COOKIE)handle)->intf = intf; #endif /* USB_SUPPORT_SELECTIVE_SUSPEND */ #endif /* CONFIG_PM */ /* set/get operators to/from DRIVER module */ #ifdef OS_ABL_FUNC_SUPPORT /* get DRIVER operations */ RtmpNetOpsInit(pRtmpDrvNetOps); RTMP_DRV_OPS_FUNCTION(pRtmpDrvOps, pRtmpDrvNetOps, NULL, NULL); RtmpNetOpsSet(pRtmpDrvNetOps); #endif /* OS_ABL_FUNC_SUPPORT */ rv = RTMPAllocAdapterBlock(handle, &pAd); if (rv != NDIS_STATUS_SUCCESS) { /* kfree(handle); */ os_free_mem(NULL, handle); goto err_out; } /*USBDevInit============================================== */ if (USBDevConfigInit(usb_dev, intf, pAd) == FALSE) goto err_out_free_radev; RtmpRaDevCtrlInit(pAd, RTMP_DEV_INF_USB); /*NetDevInit============================================== */ net_dev = RtmpPhyNetDevInit(pAd, &netDevHook); if (net_dev == NULL) goto err_out_free_radev; /* Here are the net_device structure with usb specific parameters. */ #ifdef NATIVE_WPA_SUPPLICANT_SUPPORT /* for supporting Network Manager. * Set the sysfs physical device reference for the network logical device if set prior to registration will * cause a symlink during initialization. */ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) SET_NETDEV_DEV(net_dev, &(usb_dev->dev)); #endif #endif /* NATIVE_WPA_SUPPLICANT_SUPPORT */ #ifdef CONFIG_STA_SUPPORT /* pAd->StaCfg.OriDevType = net_dev->type; */ RTMP_DRIVER_STA_DEV_TYPE_SET(pAd, net_dev->type); #endif /* CONFIG_STA_SUPPORT */ /*All done, it's time to register the net device to linux kernel. */ /* Register this device */ #ifdef RT_CFG80211_SUPPORT { /* pAd->pCfgDev = &(usb_dev->dev); */ /* pAd->CFG80211_Register = CFG80211_Register; */ /* RTMP_DRIVER_CFG80211_INIT(pAd, usb_dev); */ /* In 2.6.32, cfg80211 register must be before register_netdevice(); We can not put the register in rt28xx_open(); Or you will suffer NULL pointer in list_add of cfg80211_netdev_notifier_call(). */ CFG80211_Register(pAd, &(usb_dev->dev), net_dev); } #endif /* RT_CFG80211_SUPPORT */ RTMP_DRIVER_OP_MODE_GET(pAd, &OpMode); status = RtmpOSNetDevAttach(OpMode, net_dev, &netDevHook); if (status != 0) goto err_out_free_netdev; /*#ifdef KTHREAD_SUPPORT */ *ppAd = pAd; #ifdef INF_PPA_SUPPORT /* pAd->pDirectpathCb = (PPA_DIRECTPATH_CB *) kmalloc (sizeof(PPA_DIRECTPATH_CB), GFP_ATOMIC); */ /* os_alloc_mem(NULL, (UCHAR **)&(pAd->pDirectpathCb), sizeof(PPA_DIRECTPATH_CB)); */ RTMP_DRIVER_INF_PPA_INIT(pAd); #endif /* INF_PPA_SUPPORT */ #ifdef PRE_ASSIGN_MAC_ADDR UCHAR PermanentAddress[MAC_ADDR_LEN]; RTMP_DRIVER_MAC_ADDR_GET(pAd, &PermanentAddress[0]); DBGPRINT(RT_DEBUG_TRACE, ("@%s MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n", __FUNCTION__, PermanentAddress[0], PermanentAddress[1],PermanentAddress[2],PermanentAddress[3],PermanentAddress[4],PermanentAddress[5])); /* Set up the Mac address */ RtmpOSNetDevAddrSet(OpMode, net_dev, &PermanentAddress[0], NULL); #endif /* PRE_ASSIGN_MAC_ADDR */ #ifdef EXT_BUILD_CHANNEL_LIST RTMP_DRIVER_SET_PRECONFIG_VALUE(pAd); #endif /* EXT_BUILD_CHANNEL_LIST */ #if defined(CONFIG_HAS_EARLYSUSPEND) || defined(CONFIG_ANDROID_POWER) ((PRTMP_ADAPTER)pAd)->early_suspend.suspend = NULL; RTRegisterEarlySuspend(pAd); #endif DBGPRINT(RT_DEBUG_TRACE, ("<===rt2870_probe()!\n")); return 0; /* --------------------------- ERROR HANDLE --------------------------- */ err_out_free_netdev: RtmpOSNetDevFree(net_dev); err_out_free_radev: RTMPFreeAdapter(pAd); err_out: *ppAd = NULL; return -1; }
static void usb_net_raw_ip_tx_urb_work(struct work_struct *work) { struct baseband_usb *usb = container_of(work, struct baseband_usb, usb.tx_work); struct urb *urb; int err; if (verbose) pr_info("usb_net_raw_ip_tx_urb_work {\n"); /* check if tx urb(s) queued */ if (usb == NULL || (!usb->usb.tx_urb && usb_anchor_empty(&usb->usb.tx_urb_deferred))) { pr_debug("%s: nothing to do!\n", __func__); return; } /* check if suspended */ if (usb->susp_count > 0) { pr_info("%s: usb->susp_count %d > 0 (suspended)\n", __func__, usb->susp_count); return; } /* submit queued tx urb(s) */ while ((urb = usb_get_from_anchor(&usb->usb.tx_urb_deferred)) != (struct urb *) 0) { /* 77969-7 patch */ /* decrement count from usb_get_from_anchor() */ usb_free_urb(urb); /* check if usb interface disconnected */ if (!usb->usb.interface) { pr_err("%s: not submitting tx urb %p" " - interface disconnected\n", __func__, urb); if (urb->transfer_buffer) { kfree(urb->transfer_buffer); urb->transfer_buffer = (void *) 0; } usb_free_urb(urb); continue; } /* 77969-7 patch */ /* autoresume before tx */ usb_mark_last_busy(usb->usb.device); #if 0 err = usb_autopm_get_interface(usb->usb.interface); if (err < 0) { pr_err("%s: usb_autopm_get_interface(%p) failed %d\n", __func__, usb->usb.interface, err); /* 77969-7 patch */ if (urb->transfer_buffer) { kfree(urb->transfer_buffer); urb->transfer_buffer = (void *) 0; } /* 77969-7 patch */ usb_free_urb(urb); continue; } #endif /* submit tx urb */ err = usb_submit_urb(urb, GFP_ATOMIC); if (err < 0) { /* 77969-7 patch */ pr_err("%s: usb_submit_urb(%p) failed - err %d\n", __func__, urb, err); /* 77969-7 patch */ //usb_autopm_put_interface(usb->usb.interface); usb_autopm_put_interface_async(usb->usb.interface); /* 77969-7 patch */ if (urb->transfer_buffer) { kfree(urb->transfer_buffer); urb->transfer_buffer = (void *) 0; } /* 77969-7 patch */ usb_free_urb(urb); continue; } /* 77969-7 patch */ /* free tx urb * - actual urb free occurs when refcnt which was incremented * in usb_submit_urb is decremented to 0 (usually after urb * completion function returns) * - tx urb transfer buffer will be freed in urb completion * function */ usb_free_urb(urb); /* 77969-7 patch */ } if (verbose) pr_info("usb_net_raw_ip_tx_urb_work }\n"); }
static int InterfaceAbortIdlemode(PMINI_ADAPTER Adapter, unsigned int Pattern) { int status = STATUS_SUCCESS; unsigned int value; unsigned int chip_id ; unsigned long timeout = 0 ,itr = 0; int lenwritten = 0; unsigned char aucAbortPattern[8]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; PS_INTERFACE_ADAPTER psInterfaceAdapter = Adapter->pvInterfaceAdapter; //Abort Bus suspend if its already suspended if((TRUE == psInterfaceAdapter->bSuspended) && (TRUE == Adapter->bDoSuspend)) { status = usb_autopm_get_interface(psInterfaceAdapter->interface); BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"Bus got wakeup..Aborting Idle mode... status:%d \n",status); } if((Adapter->ulPowerSaveMode == DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING) || (Adapter->ulPowerSaveMode == DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE)) { //write the SW abort pattern. BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "Writing pattern<%d> to SW_ABORT_IDLEMODE_LOC\n", Pattern); status = wrmalt(Adapter,SW_ABORT_IDLEMODE_LOC, &Pattern, sizeof(Pattern)); if(status) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"WRM to Register SW_ABORT_IDLEMODE_LOC failed.."); return status; } } if(Adapter->ulPowerSaveMode == DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING) { value = 0x80000000; status = wrmalt(Adapter,DEBUG_INTERRUPT_GENERATOR_REGISTOR, &value, sizeof(value)); if(status) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"WRM to DEBUG_INTERRUPT_GENERATOR_REGISTOR Register failed"); return status; } } else if(Adapter->ulPowerSaveMode != DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE) { /* * Get a Interrupt Out URB and send 8 Bytes Down * To be Done in Thread Context. * Not using Asynchronous Mechanism. */ status = usb_interrupt_msg (psInterfaceAdapter->udev, usb_sndintpipe(psInterfaceAdapter->udev, psInterfaceAdapter->sIntrOut.int_out_endpointAddr), aucAbortPattern, 8, &lenwritten, 5000); if(status) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "Sending Abort pattern down fails with status:%d..\n",status); return status; } else { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "NOB Sent down :%d", lenwritten); } //mdelay(25); timeout= jiffies + msecs_to_jiffies(50) ; while( timeout > jiffies ) { itr++ ; rdmalt(Adapter, CHIP_ID_REG, &chip_id, sizeof(UINT)); if(0xbece3200==(chip_id&~(0xF0))) { chip_id = chip_id&~(0xF0); } if(chip_id == Adapter->chip_id) break; } if(timeout < jiffies ) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"Not able to read chip-id even after 25 msec"); } else { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"Number of completed iteration to read chip-id :%lu", itr); } status = wrmalt(Adapter,SW_ABORT_IDLEMODE_LOC, &Pattern, sizeof(status)); if(status) { BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"WRM to Register SW_ABORT_IDLEMODE_LOC failed.."); return status; } } return status; }
static int rt2870_resume( struct usb_interface *intf) { struct net_device *net_dev; VOID *pAd = usb_get_intfdata(intf); #if (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) UCHAR Flag; #endif /* (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) */ #ifdef USB_SUPPORT_SELECTIVE_SUSPEND INT pm_usage_cnt; UCHAR Flag; #endif /* USB_SUPPORT_SELECTIVE_SUSPEND */ #if (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) RTMP_DRIVER_ADAPTER_RT28XX_WOW_STATUS(pAd, &Flag); #endif /* (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) */ #ifdef USB_SUPPORT_SELECTIVE_SUSPEND #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) pm_usage_cnt = atomic_read(&intf->pm_usage_cnt); #else pm_usage_cnt = intf->pm_usage_cnt; #endif if(pm_usage_cnt <= 0) usb_autopm_get_interface(intf); DBGPRINT(RT_DEBUG_ERROR, ("autosuspend===> rt2870_resume()\n")); /*RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_SUSPEND); */ RTMP_DRIVER_ADAPTER_SUSPEND_CLEAR(pAd); #if (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) if (Flag == FALSE) #endif /* (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) */ /*RT28xxUsbAsicRadioOn(pAd); */ RTMP_DRIVER_ADAPTER_RT28XX_USB_ASICRADIO_ON(pAd); DBGPRINT(RT_DEBUG_ERROR, ("autosuspend<=== rt2870_resume()\n")); return 0; #endif /* USB_SUPPORT_SELECTIVE_SUSPEND */ DBGPRINT(RT_DEBUG_TRACE, ("===> rt2870_resume()\n")); #if (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) if (Flag == TRUE) RTMP_DRIVER_ADAPTER_RT28XX_WOW_DISABLE(pAd); else #endif /* (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) */ { RTMP_DRIVER_ADAPTER_SUSPEND_CLEAR(pAd); RTMP_DRIVER_ADAPTER_RT28XX_USB_ASICRADIO_ON(pAd); } DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2870_resume()\n")); return 0; }
/* * Synchronous write to the device * * Takes care of updating EDC counts and thus, handle device errors. */ static ssize_t i2400mu_tx_bulk_out(struct i2400mu *i2400mu, void *buf, size_t buf_size) { int result; struct device *dev = &i2400mu->usb_iface->dev; int len; struct usb_endpoint_descriptor *epd; int pipe, do_autopm = 1; result = usb_autopm_get_interface(i2400mu->usb_iface); if (result < 0) { dev_err(dev, "BM-CMD: can't get autopm: %d\n", result); do_autopm = 0; } epd = usb_get_epd(i2400mu->usb_iface, i2400mu->endpoint_cfg.bulk_out); pipe = usb_sndbulkpipe(i2400mu->usb_dev, epd->bEndpointAddress); retry: result = usb_bulk_msg(i2400mu->usb_dev, pipe, buf, buf_size, &len, 200); switch (result) { case 0: if (len != buf_size) { dev_err(dev, "BM-CMD: short write (%u B vs %zu " "expected)\n", len, buf_size); result = -EIO; break; } result = len; 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"); 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: result = -ESHUTDOWN; break; case -ETIMEDOUT: /* bah... */ break; default: /* any other? */ if (edc_inc(&i2400mu->urb_edc, EDC_MAX_ERRORS, EDC_ERROR_TIMEFRAME)) { dev_err(dev, "BM-CMD: maximum errors in " "URB exceeded; resetting device\n"); usb_queue_reset_device(i2400mu->usb_iface); result = -ENODEV; break; } dev_err(dev, "BM-CMD: URB error %d, retrying\n", result); goto retry; } if (do_autopm) usb_autopm_put_interface(i2400mu->usb_iface); return result; }
/* * Read an ack from the notification endpoint * * @i2400m: * @_ack: pointer to where to store the read data * @ack_size: how many bytes we should read * * Returns: < 0 errno code on error; otherwise, amount of received bytes. * * Submits a notification read, appends the read data to the given ack * buffer and then repeats (until @ack_size bytes have been * received). */ ssize_t i2400mu_bus_bm_wait_for_ack(struct i2400m *i2400m, struct i2400m_bootrom_header *_ack, size_t ack_size) { ssize_t result = -ENOMEM; struct device *dev = i2400m_dev(i2400m); struct i2400mu *i2400mu = container_of(i2400m, struct i2400mu, i2400m); struct urb notif_urb; void *ack = _ack; size_t offset, len; long val; int do_autopm = 1; DECLARE_COMPLETION_ONSTACK(notif_completion); d_fnstart(8, dev, "(i2400m %p ack %p size %zu)\n", i2400m, ack, ack_size); BUG_ON(_ack == i2400m->bm_ack_buf); result = usb_autopm_get_interface(i2400mu->usb_iface); if (result < 0) { dev_err(dev, "BM-ACK: can't get autopm: %d\n", (int) result); do_autopm = 0; } usb_init_urb(¬if_urb); /* ready notifications */ usb_get_urb(¬if_urb); offset = 0; while (offset < ack_size) { init_completion(¬if_completion); result = i2400mu_notif_submit(i2400mu, ¬if_urb, ¬if_completion); if (result < 0) goto error_notif_urb_submit; val = wait_for_completion_interruptible_timeout( ¬if_completion, HZ); if (val == 0) { result = -ETIMEDOUT; usb_kill_urb(¬if_urb); /* Timedout */ goto error_notif_wait; } if (val == -ERESTARTSYS) { result = -EINTR; /* Interrupted */ usb_kill_urb(¬if_urb); goto error_notif_wait; } result = notif_urb.status; /* How was the ack? */ switch (result) { case 0: break; case -EINVAL: /* while removing driver */ case -ENODEV: /* dev disconnect ... */ case -ENOENT: /* just ignore it */ case -ESHUTDOWN: /* and exit */ case -ECONNRESET: result = -ESHUTDOWN; goto error_dev_gone; default: /* any other? */ usb_kill_urb(¬if_urb); /* Timedout */ if (edc_inc(&i2400mu->urb_edc, EDC_MAX_ERRORS, EDC_ERROR_TIMEFRAME)) goto error_exceeded; dev_err(dev, "BM-ACK: URB error %d, " "retrying\n", notif_urb.status); continue; /* retry */ } if (notif_urb.actual_length == 0) { d_printf(6, dev, "ZLP received, retrying\n"); continue; } /* Got data, append it to the buffer */ len = min(ack_size - offset, (size_t) notif_urb.actual_length); memcpy(ack + offset, i2400m->bm_ack_buf, len); offset += len; } result = offset; error_notif_urb_submit: error_notif_wait: error_dev_gone: out: if (do_autopm) usb_autopm_put_interface(i2400mu->usb_iface); d_fnend(8, dev, "(i2400m %p ack %p size %zu) = %ld\n", i2400m, ack, ack_size, (long) result); return result; error_exceeded: dev_err(dev, "bm: maximum errors in notification URB exceeded; " "resetting device\n"); usb_queue_reset_device(i2400mu->usb_iface); goto out; }
/* 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)) { //HTC+++ //lock cpu perf usbnet_lock_perf(); //queue usbnet_unlock_perf_delayed_work usbnet_rx_len = 0; schedule_delayed_work(&usbnet_unlock_perf_delayed_work, msecs_to_jiffies(PM_QOS_USBNET_PERF_UNLOCK_TIMER)); pr_info("%s(%d) [USBNET] EVENT_RX_HALT unlink_urbs !!!\n", __func__, __LINE__); pr_info("%s(%d) [USBNET] dev->rxq.qlen:%d\n", __func__, __LINE__, dev->rxq.qlen); //HTC--- 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); //HTC+++ pr_info("%s(%d) [USBNET] EVENT_RX_HALT usb_clear_halt:%d !!!\n", __func__, __LINE__, status); //HTC--- 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 { //HTC+++ pr_info("%s(%d) [USBNET] clear_bit EVENT_RX_HALT !!!\n", __func__, __LINE__); //HTC--- 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); }
/*=========================================================================== METHOD: GobiUSBNetAutoPMThread (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 GobiUSBNetAutoPMThread( void * pData ) { unsigned long activeURBflags, URBListFlags; sURBList * pURBListEntry; int status; struct usb_device * pUdev; sAutoPM * pAutoPM = (sAutoPM *)pData; struct urb * pURB; 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 ); pURB = pAutoPM->mpActiveURB; spin_unlock_irqrestore( &pAutoPM->mActiveURBLock, activeURBflags ); if (pURB != NULL) { usb_kill_urb( pURB ); } // Will be freed in callback function // Cleanup URB List spin_lock_irqsave( &pAutoPM->mURBListLock, URBListFlags ); pURBListEntry = pAutoPM->mpURBList; while (pURBListEntry != NULL) { pAutoPM->mpURBList = pAutoPM->mpURBList->mpNext; atomic_dec( &pAutoPM->mURBListLen ); 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; atomic_dec( &pAutoPM->mURBListLen ); 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 (LINUX_VERSION_CODE > KERNEL_VERSION( 2,6,23 )) 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 GobiSuspend( pAutoPM->mpIntf, PMSG_SUSPEND ); } // Add pURBListEntry back onto pAutoPM->mpURBList spin_lock_irqsave( &pAutoPM->mURBListLock, URBListFlags ); pURBListEntry->mpNext = pAutoPM->mpURBList; pAutoPM->mpURBList = pURBListEntry; atomic_inc( &pAutoPM->mURBListLen ); 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; } #endif // 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; }
int rausb_autopm_get_interface( void *intf) { return usb_autopm_get_interface((struct usb_interface *)intf); }
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) { if (netif_msg_ifup (dev)) devinfo (dev, "resumption fail (%d) usbnet usb-%s-%s, %s", 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) { if (netif_msg_ifup (dev)) devinfo (dev, "open reset fail (%d) usbnet usb-%s-%s, %s", 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) { if (netif_msg_ifup (dev)) devdbg (dev, "can't open; %d", retval); goto done; } /* start any status interrupt transfer */ if (dev->interrupt) { retval = usb_submit_urb (dev->interrupt, GFP_KERNEL); if (retval < 0) { if (netif_msg_ifup (dev)) deverr (dev, "intr submit %d", retval); goto done; } } netif_start_queue (net); if (netif_msg_ifup (dev)) { char *framing; if (dev->driver_info->flags & FLAG_FRAMING_NC) framing = "NetChip"; else if (dev->driver_info->flags & FLAG_FRAMING_GL) framing = "GeneSys"; else if (dev->driver_info->flags & FLAG_FRAMING_Z) framing = "Zaurus"; else if (dev->driver_info->flags & FLAG_FRAMING_RN) framing = "RNDIS"; else if (dev->driver_info->flags & FLAG_FRAMING_AX) framing = "ASIX"; else framing = "simple"; devinfo (dev, "open: enable queueing " "(rx %d, tx %d) mtu %d %s framing", (int)RX_QLEN (dev), (int)TX_QLEN (dev), dev->net->mtu, framing); } // delay posting reads until we're fully open tasklet_schedule (&dev->bh); #if defined(CONFIG_ERICSSON_F3307_ENABLE) if (info->manage_power) { retval = info->manage_power(dev, 1); if (retval < 0) goto done; usb_autopm_put_interface(dev->intf); } #endif return retval; done: usb_autopm_put_interface(dev->intf); done_nopm: return retval; }
static int rt2870_probe( struct usb_interface *intf, struct usb_device *usb_dev, const USB_DEVICE_ID *dev_id, VOID **ppAd) { struct net_device *net_dev = NULL; #ifdef RESUME_WITH_USB_RESET_SUPPORT VOID *pAd = (VOID *) gpAd; #else VOID *pAd = (VOID *) NULL; #endif /* RESUME_WITH_USB_RESET_SUPPORT */ INT status, rv; PVOID handle; RTMP_OS_NETDEV_OP_HOOK netDevHook; ULONG OpMode; #ifdef CONFIG_PM #ifdef USB_SUPPORT_SELECTIVE_SUSPEND /* INT pm_usage_cnt; */ INT res =1 ; #endif /* USB_SUPPORT_SELECTIVE_SUSPEND */ #endif /* CONFIG_PM */ DBGPRINT(RT_DEBUG_TRACE, ("===>rt2870_probe()!\n")); #ifdef CONFIG_PM #ifdef USB_SUPPORT_SELECTIVE_SUSPEND res = usb_autopm_get_interface(intf); if (res) { DBGPRINT(RT_DEBUG_ERROR, ("rt2870_probe autopm_resume fail ------\n")); return -EIO; } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) atomic_set(&intf->pm_usage_cnt, 1); printk(" rt2870_probe ====> pm_usage_cnt %d \n", atomic_read(&intf->pm_usage_cnt)); #else intf->pm_usage_cnt = 1; printk(" rt2870_probe ====> pm_usage_cnt %d \n", intf->pm_usage_cnt); #endif #endif /* USB_SUPPORT_SELECTIVE_SUSPEND */ #endif /* CONFIG_PM */ os_alloc_mem(NULL, (UCHAR **)&handle, sizeof(struct os_cookie)); if (handle == NULL) { printk("rt2870_probe(): Allocate memory for os handle failed!\n"); return -ENOMEM; } memset(handle, 0, sizeof(struct os_cookie)); ((POS_COOKIE)handle)->pUsb_Dev = usb_dev; #ifdef CONFIG_PM #ifdef USB_SUPPORT_SELECTIVE_SUSPEND ((POS_COOKIE)handle)->intf = intf; #endif /* USB_SUPPORT_SELECTIVE_SUSPEND */ #endif /* CONFIG_PM */ /* set/get operators to/from DRIVER module */ #ifdef OS_ABL_FUNC_SUPPORT /* get DRIVER operations */ RtmpNetOpsInit(pRtmpDrvNetOps); RTMP_DRV_OPS_FUNCTION(pRtmpDrvOps, pRtmpDrvNetOps, NULL, NULL); RtmpNetOpsSet(pRtmpDrvNetOps); #endif /* OS_ABL_FUNC_SUPPORT */ #ifdef RESUME_WITH_USB_RESET_SUPPORT if (rtusb_fast_probe(handle, &pAd, intf) == NDIS_STATUS_SUCCESS) { *ppAd = pAd; goto fast_probe_done; } #endif /* RESUME_WITH_USB_RESET_SUPPORT */ rv = RTMPAllocAdapterBlock(handle, &pAd); if (rv != NDIS_STATUS_SUCCESS) { os_free_mem(NULL, handle); goto err_out; } if (USBDevConfigInit(usb_dev, intf, pAd) == FALSE) goto err_out_free_radev; RTMP_DRIVER_USB_INIT(pAd, usb_dev, dev_id->driver_info); net_dev = RtmpPhyNetDevInit(pAd, &netDevHook); if (net_dev == NULL) goto err_out_free_radev; /* Here are the net_device structure with usb specific parameters. */ #ifdef NATIVE_WPA_SUPPLICANT_SUPPORT /* for supporting Network Manager. * Set the sysfs physical device reference for the network logical device if set prior to registration will * cause a symlink during initialization. */ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) SET_NETDEV_DEV(net_dev, &(usb_dev->dev)); #endif #endif /* NATIVE_WPA_SUPPLICANT_SUPPORT */ #ifdef CONFIG_STA_SUPPORT /* pAd->StaCfg.OriDevType = net_dev->type; */ RTMP_DRIVER_STA_DEV_TYPE_SET(pAd, net_dev->type); #ifdef PROFILE_PATH_DYNAMIC RTMP_DRIVER_STA_PROFILEPATH_SET(pAd, (ULONG)profilePath); #endif /* PROFILE_PATH_DYNAMIC */ #endif /* CONFIG_STA_SUPPORT */ /*All done, it's time to register the net device to linux kernel. */ /* Register this device */ #ifdef RT_CFG80211_SUPPORT { /* pAd->pCfgDev = &(usb_dev->dev); */ /* pAd->CFG80211_Register = CFG80211_Register; */ /* RTMP_DRIVER_CFG80211_INIT(pAd, usb_dev); */ /* In 2.6.32, cfg80211 register must be before register_netdevice(); We can not put the register in rt28xx_open(); Or you will suffer NULL pointer in list_add of cfg80211_netdev_notifier_call(). */ CFG80211_Register(pAd, &(usb_dev->dev), net_dev); } #endif /* RT_CFG80211_SUPPORT */ RTMP_DRIVER_OP_MODE_GET(pAd, &OpMode); status = RtmpOSNetDevAttach(OpMode, net_dev, &netDevHook); if (status != 0) goto err_out_free_netdev; /*#ifdef KTHREAD_SUPPORT */ #if 0 /* move to RtmpOSTaskInit() */ { RT_CMD_WAIT_QUEUE_LIST List, *pList = &List; RTMP_DRIVER_TASK_LIST_GET(pAd, &List); init_waitqueue_head(&(RTMP_OS_TASK_GET(pList->pMlmeTask)->kthread_q)); #ifdef RTMP_TIMER_TASK_SUPPORT init_waitqueue_head(&(RTMP_OS_TASK_GET(pList->pTimerTask)->kthread_q)); #endif /* RTMP_TIMER_TASK_SUPPORT */ init_waitqueue_head(&(RTMP_OS_TASK_GET(pList->pCmdQTask)->kthread_q)); #ifdef WSC_INCLUDED init_waitqueue_head(&(RTMP_OS_TASK_GET(pList->pWscTask)->kthread_q)); #endif /* WSC_INCLUDED */ } #endif /* KTHREAD_SUPPORT */ *ppAd = pAd; #ifdef RESUME_WITH_USB_RESET_SUPPORT gpAd = pAd; #endif /* RESUME_WITH_USB_RESET_SUPPORT */ #ifdef INF_PPA_SUPPORT RTMP_DRIVER_INF_PPA_INIT(pAd); #endif /* INF_PPA_SUPPORT */ #ifdef PRE_ASSIGN_MAC_ADDR { UCHAR PermanentAddress[MAC_ADDR_LEN]; RTMP_DRIVER_MAC_ADDR_GET(pAd, &PermanentAddress[0]); DBGPRINT(RT_DEBUG_TRACE, ("%s():MAC Addr - %02x:%02x:%02x:%02x:%02x:%02x\n", __FUNCTION__, PermanentAddress[0], PermanentAddress[1], PermanentAddress[2],PermanentAddress[3], PermanentAddress[4],PermanentAddress[5])); /* Set up the Mac address */ RtmpOSNetDevAddrSet(OpMode, net_dev, &PermanentAddress[0], NULL); } #endif /* PRE_ASSIGN_MAC_ADDR */ #ifdef EXT_BUILD_CHANNEL_LIST RTMP_DRIVER_SET_PRECONFIG_VALUE(pAd); #endif /* EXT_BUILD_CHANNEL_LIST */ DBGPRINT(RT_DEBUG_TRACE, ("<===rt2870_probe()!\n")); return 0; /* --------------------------- ERROR HANDLE --------------------------- */ err_out_free_netdev: RtmpOSNetDevFree(net_dev); err_out_free_radev: RTMPFreeAdapter(pAd); err_out: *ppAd = NULL; return -1; #ifdef RESUME_WITH_USB_RESET_SUPPORT fast_probe_done: printk("fast probe done\n"); return 0; #endif /* RESUME_WITH_USB_RESET_SUPPORT */ }
/* 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); #if defined(CONFIG_ERICSSON_F3307_ENABLE) status = usb_autopm_get_interface(dev->intf); if (status < 0) goto fail_pipe; #endif status = usb_clear_halt (dev->udev, dev->out); #if defined(CONFIG_ERICSSON_F3307_ENABLE) usb_autopm_put_interface(dev->intf); #endif if (status < 0 && status != -EPIPE && status != -ESHUTDOWN) { if (netif_msg_tx_err (dev)) #if defined(CONFIG_ERICSSON_F3307_ENABLE) fail_pipe: #endif deverr (dev, "can't clear tx halt, status %d", 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); #if defined(CONFIG_ERICSSON_F3307_ENABLE) status = usb_autopm_get_interface(dev->intf); if (status < 0) goto fail_halt; #endif status = usb_clear_halt (dev->udev, dev->in); #if defined(CONFIG_ERICSSON_F3307_ENABLE) usb_autopm_put_interface(dev->intf); #endif if (status < 0 && status != -EPIPE && status != -ESHUTDOWN) { if (netif_msg_rx_err (dev)) #if defined(CONFIG_ERICSSON_F3307_ENABLE) fail_halt: #endif deverr (dev, "can't clear rx halt, status %d", 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; 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); #if defined(CONFIG_ERICSSON_F3307_ENABLE) status = usb_autopm_get_interface(dev->intf); if (status < 0) goto fail_lowmem; #endif rx_submit (dev, urb, GFP_KERNEL); #if defined(CONFIG_ERICSSON_F3307_ENABLE) usb_autopm_put_interface(dev->intf); fail_lowmem: #endif 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); #if defined(CONFIG_ERICSSON_F3307_ENABLE) status = usb_autopm_get_interface(dev->intf); if (status < 0) goto skip_reset; #endif if(info->link_reset && (retval = info->link_reset(dev)) < 0) { #if defined(CONFIG_ERICSSON_F3307_ENABLE) usb_autopm_put_interface(dev->intf); skip_reset: #endif devinfo(dev, "link reset failed (%d) usbnet usb-%s-%s, %s", retval, dev->udev->bus->bus_name, dev->udev->devpath, info->description); #if defined(CONFIG_ERICSSON_F3307_ENABLE) } else { usb_autopm_put_interface(dev->intf); #endif } } if (dev->flags) devdbg (dev, "kevent done, flags = 0x%lx", dev->flags); }
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 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++) { 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)) { 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); mutex_unlock(&acm->mutex); out: mutex_unlock(&open_mutex); return rv; full_bailout: usb_kill_urb(acm->ctrlurb); 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 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; desc->outbuf = 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->lock); 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); rv = usb_submit_urb(desc->command, GFP_KERNEL); if (rv < 0) { kfree(buf); 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->lock); 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); queue_work(usbnet_wq, &dev->bh_w); } } /* 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) queue_work(usbnet_wq, &dev->bh_w); } } 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); }
static void ksb_start_rx_work(struct work_struct *w) { struct ks_bridge *ksb = container_of(w, struct ks_bridge, start_rx_work); struct data_pkt *pkt; struct urb *urb; int i = 0; int ret; bool put = true; ret = usb_autopm_get_interface(ksb->ifc); if (ret < 0) { if (ret != -EAGAIN && ret != -EACCES) { pr_err_ratelimited("%s: autopm_get failed:%d", ksb->fs_dev.name, ret); return; } put = false; } for (i = 0; i < NO_RX_REQS; i++) { if (!test_bit(USB_DEV_CONNECTED, &ksb->flags)) break; pkt = ksb_alloc_data_pkt(MAX_DATA_PKT_SIZE, GFP_KERNEL, ksb); if (IS_ERR(pkt)) { dev_err(&ksb->udev->dev, "unable to allocate data pkt"); break; } urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) { dev_err(&ksb->udev->dev, "unable to allocate urb"); ksb_free_data_pkt(pkt); break; } usb_fill_bulk_urb(urb, ksb->udev, ksb->in_pipe, pkt->buf, pkt->len, ksb_rx_cb, pkt); usb_anchor_urb(urb, &ksb->submitted); dbg_log_event(ksb, "S RX_URB", pkt->len, 0); atomic_inc(&ksb->rx_pending_cnt); ret = usb_submit_urb(urb, GFP_KERNEL); if (ret) { dev_err(&ksb->udev->dev, "in urb submission failed"); usb_unanchor_urb(urb); usb_free_urb(urb); ksb_free_data_pkt(pkt); atomic_dec(&ksb->rx_pending_cnt); wake_up(&ksb->pending_urb_wait); break; } usb_free_urb(urb); } if (put) usb_autopm_put_interface_async(ksb->ifc); }
/* * The parsing of the command line works exactly like the * serial.c code, except that the specifier is "ttyUSB" instead * of "ttyS". */ static int usb_console_setup(struct console *co, char *options) { struct usbcons_info *info = &usbcons_info; int baud = 9600; int bits = 8; int parity = 'n'; int doflow = 0; int cflag = CREAD | HUPCL | CLOCAL; char *s; struct usb_serial *serial; struct usb_serial_port *port; int retval; struct tty_struct *tty = NULL; struct ktermios dummy; dbg("%s", __func__); if (options) { baud = simple_strtoul(options, NULL, 10); s = options; while (*s >= '0' && *s <= '9') s++; if (*s) parity = *s++; if (*s) bits = *s++ - '0'; if (*s) doflow = (*s++ == 'r'); } /* Sane default */ if (baud == 0) baud = 9600; switch (bits) { case 7: cflag |= CS7; break; default: case 8: cflag |= CS8; break; } switch (parity) { case 'o': case 'O': cflag |= PARODD; break; case 'e': case 'E': cflag |= PARENB; break; } co->cflag = cflag; /* * no need to check the index here: if the index is wrong, console * code won't call us */ serial = usb_serial_get_by_index(co->index); if (serial == NULL) { /* no device is connected yet, sorry :( */ err("No USB device connected to ttyUSB%i", co->index); return -ENODEV; } retval = usb_autopm_get_interface(serial->interface); if (retval) goto error_get_interface; port = serial->port[co->index - serial->minor]; tty_port_tty_set(&port->port, NULL); info->port = port; ++port->port.count; if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags)) { if (serial->type->set_termios) { /* * allocate a fake tty so the driver can initialize * the termios structure, then later call set_termios to * configure according to command line arguments */ tty = kzalloc(sizeof(*tty), GFP_KERNEL); if (!tty) { retval = -ENOMEM; err("no more memory"); goto reset_open_count; } kref_init(&tty->kref); tty_port_tty_set(&port->port, tty); tty->driver = usb_serial_tty_driver; tty->index = co->index; if (tty_init_termios(tty)) { retval = -ENOMEM; err("no more memory"); goto free_tty; } } /* only call the device specific open if this * is the first time the port is opened */ if (serial->type->open) retval = serial->type->open(NULL, port); else retval = usb_serial_generic_open(NULL, port); if (retval) { err("could not open USB console port"); goto fail; } if (serial->type->set_termios) { tty->termios->c_cflag = cflag; tty_termios_encode_baud_rate(tty->termios, baud, baud); memset(&dummy, 0, sizeof(struct ktermios)); serial->type->set_termios(tty, port, &dummy); tty_port_tty_set(&port->port, NULL); kfree(tty); } set_bit(ASYNCB_INITIALIZED, &port->port.flags); } /* Now that any required fake tty operations are completed restore * the tty port count */ --port->port.count; /* The console is special in terms of closing the device so * indicate this port is now acting as a system console. */ port->port.console = 1; mutex_unlock(&serial->disc_mutex); return retval; fail: tty_port_tty_set(&port->port, NULL); free_tty: kfree(tty); reset_open_count: port->port.count = 0; usb_autopm_put_interface(serial->interface); error_get_interface: usb_serial_put(serial); mutex_unlock(&serial->disc_mutex); return retval; }
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); 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; } /* 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_dbg(dev->devicep, "%s: Unable to resume interface: %d\n", __func__, result); /* * Revisit: if (result == -EPERM) * rmnet_usb_suspend(dev->intf, PMSG_SUSPEND); */ usb_free_urb(sndurb); kfree(out_ctlreq); return result; } 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); return result; } return size; }
int diag_bridge_write(int id, char *data, int size) { struct urb *urb = NULL; unsigned int pipe; struct diag_bridge *dev; int ret; if (id < 0 || id >= MAX_DIAG_BRIDGE_DEVS) { pr_err("Invalid device ID"); return -ENODEV; } pr_debug("writing %d bytes", size); dev = __dev[id]; if (!dev) { pr_err("device is disconnected"); return -ENODEV; } mutex_lock(&dev->ifc_mutex); if (!dev->ifc) { ret = -ENODEV; goto error; } if (!dev->ops) { pr_err("bridge is not open"); ret = -ENODEV; goto error; } if (!size) { dev_err(&dev->ifc->dev, "invalid size:%d\n", size); ret = -EINVAL; goto error; } /* if there was a previous unrecoverable error, just quit */ if (dev->err) { ret = -ENODEV; goto error; } 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 put_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); put_error: if (ret) /* otherwise this is done in the completion handler */ kref_put(&dev->kref, diag_bridge_delete); error: mutex_unlock(&dev->ifc_mutex); 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 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; 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 rt2870_resume( struct usb_interface *intf) { struct net_device *net_dev; VOID *pAd = usb_get_intfdata(intf); #ifdef USB_SUPPORT_SELECTIVE_SUSPEND struct usb_device *pUsb_Dev; UCHAR Flag; int pm_usage_cnt; RTMP_DRIVER_USB_DEV_GET(pAd, &pUsb_Dev); RTMP_DRIVER_USB_INTF_GET(pAd, &intf); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) pm_usage_cnt = atomic_read(&intf->pm_usage_cnt); #else pm_usage_cnt = intf->pm_usage_cnt; #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33) if(pUsb_Dev->autosuspend_disabled == 0) #else if(pUsb_Dev->auto_pm == 1) #endif { if(pm_usage_cnt <= 0) usb_autopm_get_interface(intf); } DBGPRINT(RT_DEBUG_ERROR, ("autosuspend===> rt2870_resume()\n")); /*RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_SUSPEND); */ RTMP_DRIVER_ADAPTER_SUSPEND_CLEAR(pAd); RTMP_DRIVER_ADAPTER_CPU_SUSPEND_TEST(pAd, &Flag); if(Flag) /*if(RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_CPU_SUSPEND)) */ { /*RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_CPU_SUSPEND); */ RTMP_DRIVER_ADAPTER_CPU_SUSPEND_CLEAR(pAd); } /*RT28xxUsbAsicRadioOn(pAd); */ RTMP_DRIVER_ADAPTER_RT28XX_USB_ASICRADIO_ON(pAd); DBGPRINT(RT_DEBUG_ERROR, ("autosuspend<=== rt2870_resume()\n")); return 0; #endif /* USB_SUPPORT_SELECTIVE_SUSPEND */ DBGPRINT(RT_DEBUG_TRACE, ("===> rt2870_resume()\n")); /* pAd->PM_FlgSuspend = 0; */ RTMP_DRIVER_USB_RESUME(pAd); /* net_dev = pAd->net_dev; */ RTMP_DRIVER_NET_DEV_GET(pAd, &net_dev); netif_device_attach(net_dev); netif_start_queue(net_dev); netif_carrier_on(net_dev); netif_wake_queue(net_dev); DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2870_resume()\n")); return 0; }