void ctrl_bridge_close(unsigned int id) { struct ctrl_bridge *dev; if (id >= MAX_BRIDGE_DEVICES) return; dev = __dev[id]; if (!dev || !dev->brdg) return; dev_dbg(&dev->intf->dev, "%s:\n", __func__); ctrl_bridge_set_cbits(dev->brdg->ch_id, 0); dev_err(&dev->intf->dev, "%s: usb_wait_anchor_empty_timeout tx_submitted\n", __func__); usb_wait_anchor_empty_timeout(&dev->tx_submitted, 500); dev_err(&dev->intf->dev, "%s: tx_submitted usb_anchor_empty:%d\n", __func__, usb_anchor_empty(&dev->tx_submitted)); usb_unlink_anchored_urbs(&dev->tx_submitted); dev->brdg = NULL; }
int ctrl_bridge_suspend(unsigned int id) { struct ctrl_bridge *dev; unsigned long flags; if (id >= MAX_BRIDGE_DEVICES) return -EINVAL; dev = __dev[id]; if (!dev) return -ENODEV; if (!dev->int_pipe) return 0; spin_lock_irqsave(&dev->lock, flags); if (!usb_anchor_empty(&dev->tx_submitted) || dev->rx_state == RX_BUSY) { spin_unlock_irqrestore(&dev->lock, flags); return -EBUSY; } spin_unlock_irqrestore(&dev->lock, flags); usb_kill_urb(dev->inturb); spin_lock_irqsave(&dev->lock, flags); if (dev->rx_state != RX_IDLE) { spin_unlock_irqrestore(&dev->lock, flags); return -EBUSY; } if (!usb_anchor_empty(&dev->tx_submitted)) { spin_unlock_irqrestore(&dev->lock, flags); ctrl_bridge_start_read(dev, GFP_KERNEL); return -EBUSY; } set_bit(SUSPENDED, &dev->flags); spin_unlock_irqrestore(&dev->lock, flags); return 0; }
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; pr_debug("usb_net_raw_ip_tx_urb_work {\n"); /* check if tx urb(s) queued */ if (!usb->usb.tx_urb && usb_anchor_empty(&usb->usb.tx_urb_deferred)) { pr_debug("%s: nothing to do!\n", __func__); return; } /* check if usb interface disconnected */ if (!usb->usb.interface) { pr_err("%s: not submitting tx urb %p -interface disconnected\n", __func__, urb); return; } /* submit queued tx urb(s) */ while ((urb = usb_get_from_anchor(&usb->usb.tx_urb_deferred)) != (struct urb *) 0) { /* decrement count from usb_get_from_anchor() */ usb_free_urb(urb); /* autoresume before tx */ usb_mark_last_busy(usb->usb.device); 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); if (urb->transfer_buffer) { kfree(urb->transfer_buffer); urb->transfer_buffer = (void *) 0; } usb_free_urb(urb); usb->stats.tx_errors++; continue; } /* submit tx urb */ err = usb_submit_urb(urb, GFP_ATOMIC); if (err < 0) { pr_err("%s: usb_submit_urb(%p) failed - err %d\n", __func__, urb, err); usb_autopm_put_interface(usb->usb.interface); if (urb->transfer_buffer) { kfree(urb->transfer_buffer); urb->transfer_buffer = (void *) 0; } usb_free_urb(urb); continue; } /* 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); } pr_debug("usb_net_raw_ip_tx_urb_work }\n"); }