case HC_STATE_SUSPENDED: /* HC upstream links (register access, wakeup signaling) can work * even when the downstream links (and DMA etc) are quiesced; let * usbcore talk to the root hub. */ if (hcd->self.controller->power.power_state.event == PM_EVENT_ON && urb->dev->parent == NULL) goto doit; /* FALL THROUGH */ 
static int hcd_submit_urb (struct urb *urb, gfp_t mem_flags){	int			status;	struct usb_hcd		*hcd = urb->dev->bus->hcpriv;	struct usb_host_endpoint *ep;	unsigned long		flags;	if (!hcd)		return -ENODEV;	usbmon_urb_submit(&hcd->self, urb);	/*	 * Atomically queue the urb,  first to our records, then to the HCD.	 * Access to urb->status is controlled by urb->lock ... changes on	 * i/o completion (normal or fault) or unlinking.	 */	// FIXME:  verify that quiescing hc works right (RH cleans up)	spin_lock_irqsave (&hcd_data_lock, flags);	ep = (usb_pipein(urb->pipe) ? urb->dev->ep_in : urb->dev->ep_out)			[usb_pipeendpoint(urb->pipe)];	if (unlikely (!ep))		status = -ENOENT;	else if (unlikely (urb->reject))		status = -EPERM;	else switch (hcd->state) {	case HC_STATE_RUNNING:	case HC_STATE_RESUMING:		usb_get_dev (urb->dev);		list_add_tail (&urb->urb_list, &ep->urb_list);		status = 0;		break;	default:		status = -ESHUTDOWN;		break;	}	spin_unlock_irqrestore (&hcd_data_lock, flags);	if (status) {		INIT_LIST_HEAD (&urb->urb_list);		usbmon_urb_submit_error(&hcd->self, urb, status);		return status;	}	/* increment urb's reference count as part of giving it to the HCD	 * (which now controls it).  HCD guarantees that it either returns	 * an error or calls giveback(), but not both.	 */	urb = usb_get_urb (urb);	atomic_inc (&urb->use_count);	if (urb->dev == hcd->self.root_hub) {		/* NOTE:  requirement on hub callers (usbfs and the hub		 * driver, for now) that URBs' urb->transfer_buffer be		 * valid and usb_buffer_{sync,unmap}() not be needed, since		 * they could clobber root hub response data.		 */		status = rh_urb_enqueue (hcd, urb);		goto done;	}	/* lower level hcd code should use *_dma exclusively,	 * unless it uses pio or talks to another transport.	 */	if (hcd->self.controller->dma_mask) {		if (usb_pipecontrol (urb->pipe)			&& !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))			urb->setup_dma = dma_map_single (					hcd->self.controller,					urb->setup_packet,					sizeof (struct usb_ctrlrequest),					DMA_TO_DEVICE);		if (urb->transfer_buffer_length != 0			&& !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP))			urb->transfer_dma = dma_map_single (					hcd->self.controller,					urb->transfer_buffer,					urb->transfer_buffer_length,					usb_pipein (urb->pipe)					    ? DMA_FROM_DEVICE					    : DMA_TO_DEVICE);	}	status = hcd->driver->urb_enqueue (hcd, ep, urb, mem_flags);done:	if (unlikely (status)) {		urb_unlink (urb);		atomic_dec (&urb->use_count);		if (urb->reject)			wake_up (&usb_kill_urb_queue);		usb_put_urb (urb);		usbmon_urb_submit_error(&hcd->self, urb, status);	}	return status;}
10457	/local/tlutelli/issta_data/temp/c/2005_temp/2005/10457/979d5199fee9e80290ddeb532e5993bd15506712/hcd.c/buggy/drivers/usb/core/hcd.c