Ejemplo n.º 1
0
int usb_hcd_amba_remove (void *vid)
{
	struct amba_device *dev = (struct amba_id *)vid;
	struct usb_hcd *hcd = (struct usb_hcd*)(&dev->dev);

	if (!hcd) {
		printk(KERN_ERR"usb_hcd_amba_remove: dev has no drvdata!\n");
		return -ENODEV;
	}

	if (in_interrupt ())
		BUG ();

	if (HCD_IS_RUNNING (hcd->state))
		hcd->state = USB_STATE_QUIESCING;

	if (hcd->driver->stop)
		hcd->driver->stop(hcd);

	hcd->state = USB_STATE_HALT;

	free_irq(dev->irq[0], hcd);
	if (hcd->driver->flags & HCD_MEMORY) {
		iounmap (hcd->regs);
	}

	usb_set_vbus_off();
	vbus_cleanup();

	return 0;
}
Ejemplo n.º 2
0
/**
 * usb_hcd_ppc_soc_remove - shutdown processing for On-Chip HCDs
 * @pdev: USB Host Controller being removed
 * Context: !in_interrupt()
 *
 * Reverses the effect of usb_hcd_ppc_soc_probe().
 * It is always called from a thread
 * context, normally "rmmod", "apmd", or something similar.
 *
 */
static void usb_hcd_ppc_soc_remove(struct platform_device *pdev)
{
	struct usb_hcd	*hcd;
	struct resource	*res;

	hcd = dev_get_drvdata(&pdev->dev);
	if (!hcd)
		return;

	if (in_interrupt())
		BUG();

	if (HCD_IS_RUNNING(hcd->state))
		hcd->state = USB_STATE_QUIESCING;

	usb_disconnect(&hcd->self.root_hub);

	hcd->driver->stop(hcd);
	del_timer_sync(&hcd->rh_timer);
	hcd_buffer_destroy(hcd);
	hcd->state = USB_STATE_HALT;
	dev_set_drvdata(&pdev->dev, NULL);


	free_irq(hcd->irq, hcd);
	iounmap(hcd->regs);
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (res) {
		release_mem_region(res->start, res->end - res->start + 1);
	}

	usb_deregister_bus (&hcd->self);

	pr_debug("Removed PPC-SOC EHCI USB Controller\n");
}
Ejemplo n.º 3
0
static int __init_or_module arc_ehci_remove(struct device *dev)
{
	struct ehci_hcd *ehci = dev_get_drvdata(dev);
	struct usb_hcd *hcd = ehci_to_hcd(ehci);
	struct arc_usb_config *config;

	config = (struct arc_usb_config *)dev->platform_data;

	dbg("%s  dev=0x%p\n", __FUNCTION__, dev);

	if (HCD_IS_RUNNING(hcd->state))
		hcd->state = USB_STATE_QUIESCING;

	usb_disconnect(&hcd->self.root_hub);

	hcd->driver->stop(hcd);

	hcd_buffer_destroy(hcd);

	usb_deregister_bus(&hcd->self);

	free_irq(hcd->irq, hcd);

	usb_put_hcd(hcd);

	/*
	 * do platform specific un-initialization:
	 * release iomux pins, etc.
	 */
	config->platform_uninit();

	return 0;
}
Ejemplo n.º 4
0
/**
 * usb_hcd_pci_remove - shutdown processing for PCI-based HCDs
 * @dev: USB Host Controller being removed
 * Context: !in_interrupt()
 *
 * Reverses the effect of usb_hcd_pci_probe(), first invoking
 * the HCD's stop() method.  It is always called from a thread
 * context, normally "rmmod", "apmd", or something similar.
 *
 * Store this function in the HCD's struct pci_driver as remove().
 */
void usb_hcd_pci_remove (struct pci_dev *dev)
{
	struct usb_hcd		*hcd;

	hcd = pci_get_drvdata(dev);
	if (!hcd)
		return;
	dev_info (hcd->self.controller, "remove, state %x\n", hcd->state);

	if (in_interrupt ())
		BUG ();

	if (HCD_IS_RUNNING (hcd->state))
		hcd->state = USB_STATE_QUIESCING;

	dev_dbg (hcd->self.controller, "roothub graceful disconnect\n");
	usb_disconnect (&hcd->self.root_hub);

	hcd->driver->stop (hcd);
	hcd_buffer_destroy (hcd);
	hcd->state = USB_STATE_HALT;
	pci_set_drvdata(dev, NULL);

	free_irq (hcd->irq, hcd);
	if (hcd->driver->flags & HCD_MEMORY) {
		iounmap (hcd->regs);
		release_mem_region (pci_resource_start (dev, 0),
			pci_resource_len (dev, 0));
	} else {
		release_region (pci_resource_start (dev, hcd->region),
			pci_resource_len (dev, hcd->region));
	}

	usb_deregister_bus (&hcd->self);
}
Ejemplo n.º 5
0
/**
 * usb_hcd_pci_resume - power management resume of a PCI-based HCD
 * @dev: USB Host Controller being resumed
 *
 * Store this function in the HCD's struct pci_driver as resume().
 */
int usb_hcd_pci_resume (struct pci_dev *dev)
{
    struct usb_hcd		*hcd;
    int			retval;
    int			has_pci_pm;

    hcd = pci_get_drvdata(dev);
    if (hcd->state != HCD_STATE_SUSPENDED) {
        dev_dbg (hcd->self.controller,
                 "can't resume, not suspended!\n");
        return 0;
    }
    has_pci_pm = pci_find_capability(dev, PCI_CAP_ID_PM);

    /* D3cold resume isn't usually reported this way... */
    dev_dbg(hcd->self.controller, "resume from PCI %s%s\n",
            pci_state(dev->current_state),
            has_pci_pm ? "" : " (legacy)");

    hcd->state = USB_STATE_RESUMING;

    if (has_pci_pm)
        pci_set_power_state (dev, 0);
    dev->dev.power.power_state = 0;
    retval = request_irq (dev->irq, usb_hcd_irq, SA_SHIRQ,
                          hcd->description, hcd);
    if (retval < 0) {
        dev_err (hcd->self.controller,
                 "can't restore IRQ after resume!\n");
        return retval;
    }
    hcd->saw_irq = 0;
    pci_restore_state (dev);
#ifdef	CONFIG_USB_SUSPEND
    pci_enable_wake (dev, dev->current_state, 0);
    pci_enable_wake (dev, 4, 0);
#endif

    retval = hcd->driver->resume (hcd);
    if (!HCD_IS_RUNNING (hcd->state)) {
        dev_dbg (hcd->self.controller,
                 "resume fail, retval %d\n", retval);
        usb_hc_died (hcd);
    }

    return retval;
}
Ejemplo n.º 6
0
/**
 * usb_hcd_pci_resume - power management resume of a PCI-based HCD
 * @dev: USB Host Controller being resumed
 *
 * Store this function in the HCD's struct pci_driver as resume().
 */
int usb_hcd_pci_resume (struct pci_dev *dev)
{
	struct usb_hcd		*hcd;
	int			retval;
	int			has_pci_pm;

	hcd = pci_get_drvdata(dev);
	has_pci_pm = pci_find_capability(dev, PCI_CAP_ID_PM);
	if (has_pci_pm)
		dev_dbg(hcd->self.controller, "resume from state D%d\n",
				dev->current_state);

	if (hcd->state != HCD_STATE_SUSPENDED) {
		dev_dbg (hcd->self.controller, 
				"can't resume, not suspended!\n");
		return -EL3HLT;
	}
	hcd->state = USB_STATE_RESUMING;

	if (has_pci_pm)
		pci_set_power_state (dev, 0);
	dev->dev.power.power_state = 0;
	retval = request_irq (dev->irq, usb_hcd_irq, SA_SHIRQ,
				hcd->description, hcd);
	if (retval < 0) {
		dev_err (hcd->self.controller,
			"can't restore IRQ after resume!\n");
		return retval;
	}
	pci_set_master (dev);
	pci_restore_state (dev, hcd->pci_state);
#ifdef	CONFIG_USB_SUSPEND
	pci_enable_wake (dev, dev->current_state, 0);
	pci_enable_wake (dev, 4, 0);
#endif

	retval = hcd->driver->resume (hcd);
	if (!HCD_IS_RUNNING (hcd->state)) {
		dev_dbg (hcd->self.controller, 
				"resume fail, retval %d\n", retval);
		usb_hc_died (hcd);
	}

	return retval;
}
Ejemplo n.º 7
0
Archivo: hcd-pci.c Proyecto: kidoz/cxbx
/**
 * usb_hcd_pci_resume - power management resume of a PCI-based HCD
 * @dev: USB Host Controller being resumed
 *
 * Store this function in the HCD's struct pci_driver as resume().
 */
int usb_hcd_pci_resume (struct pci_dev *dev)
{
	struct usb_hcd		*hcd;
	int			retval;

	hcd = pci_get_drvdata(dev);
	dev_info (hcd->controller, "resume\n");

	/* guard against multiple resumes (APM bug?) */
	atomic_inc (&hcd->resume_count);
	if (atomic_read (&hcd->resume_count) != 1) {
		dev_err (hcd->controller, "concurrent PCI resumes\n");
		retval = 0;
		goto done;
	}

	retval = -EBUSY;
	if (hcd->state != USB_STATE_SUSPENDED) {
		dev_dbg (hcd->controller, "can't resume, not suspended!\n");
		goto done;
	}
	hcd->state = USB_STATE_RESUMING;

	pci_set_power_state (dev, 0);
	pci_restore_state (dev, hcd->pci_state);

	retval = hcd->driver->resume (hcd);
	if (!HCD_IS_RUNNING (hcd->state)) {
		dev_dbg (hcd->controller, "resume fail, retval %d\n", retval);
		usb_hc_died (hcd);
// FIXME:  recover, reset etc.
	} else {
		// FIXME for all connected devices, root-to-leaf:
		// driver->resume ();
		// proposed "new 2.5 driver model" will automate that
	}

done:
	atomic_dec (&hcd->resume_count);
	return retval;
}
Ejemplo n.º 8
0
static int
ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
{
	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
	int		ports, i, changed = 0, length = 1;
	int		can_suspend = hcd->can_wakeup;
	unsigned long	flags;

	spin_lock_irqsave (&ohci->lock, flags);

	/* handle autosuspended root:  finish resuming before
	 * letting khubd or root hub timer see state changes.
	 */
	if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER
			|| !HCD_IS_RUNNING(ohci->hcd.state)) {
		can_suspend = 0;
		goto done;
	}

	ports = roothub_a (ohci) & RH_A_NDP; 
	if (ports > MAX_ROOT_PORTS) {
		ohci_err (ohci, "bogus NDP=%d, rereads as NDP=%d\n", ports,
			  ohci_readl (ohci, &ohci->regs->roothub.a) & RH_A_NDP);
		/* retry later; "should not happen" */
		goto done;
	}

	/* init status */
	if (roothub_status (ohci) & (RH_HS_LPSC | RH_HS_OCIC))
		buf [0] = changed = 1;
	else
		buf [0] = 0;
	if (ports > 7) {
		buf [1] = 0;
		length++;
	}

	/* look at each port */
	for (i = 0; i < ports; i++) {
		u32	status = roothub_portstatus (ohci, i);

		if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC
				| RH_PS_OCIC | RH_PS_PRSC)) {
			changed = 1;
			if (i < 7)
			    buf [0] |= 1 << (i + 1);
			else
			    buf [1] |= 1 << (i - 7);
			continue;
		}

		/* can suspend if no ports are enabled; or if all all
		 * enabled ports are suspended AND remote wakeup is on.
		 */
		if (!(status & RH_PS_CCS))
			continue;
		if ((status & RH_PS_PSS) && ohci->hcd.remote_wakeup)
			continue;
		can_suspend = 0;
	}
done:
	spin_unlock_irqrestore (&ohci->lock, flags);

#ifdef CONFIG_PM
	/* save power by suspending idle root hubs;
	 * INTR_RD wakes us when there's work
	 * NOTE: if we can do this, we don't need a root hub timer!
	 */
	if (can_suspend
			&& !changed
			&& !ohci->ed_rm_list
			&& ((OHCI_CTRL_HCFS | OHCI_SCHED_ENABLES)
					& ohci->hc_control)
				== OHCI_USB_OPER
			&& time_after (jiffies, ohci->next_statechange)
			&& usb_trylock_device (hcd->self.root_hub)
			) {
		ohci_vdbg (ohci, "autosuspend\n");
		(void) ohci_hub_suspend (&ohci->hcd);
		ohci->hcd.state = USB_STATE_RUNNING;
		usb_unlock_device (hcd->self.root_hub);
	}
#endif

	return changed ? length : 0;
}
Ejemplo n.º 9
0
static int
ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
{
	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
	int		ports, i, changed = 0, length = 1;
	int		can_suspend = 1;

	ports = roothub_a (ohci) & RH_A_NDP; 
	if (ports > MAX_ROOT_PORTS) {
		if (!HCD_IS_RUNNING(ohci->hcd.state))
			return -ESHUTDOWN;
		ohci_err (ohci, "bogus NDP=%d, rereads as NDP=%d\n",
			ports, ohci_readl (&ohci->regs->roothub.a) & RH_A_NDP);
		/* retry later; "should not happen" */
		return 0;
	}

	/* init status */
	if (roothub_status (ohci) & (RH_HS_LPSC | RH_HS_OCIC))
		buf [0] = changed = 1;
	else
		buf [0] = 0;
	if (ports > 7) {
		buf [1] = 0;
		length++;
	}

	/* look at each port */
	for (i = 0; i < ports; i++) {
		u32	status = roothub_portstatus (ohci, i);

		if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC
				| RH_PS_OCIC | RH_PS_PRSC)) {
			changed = 1;
			if (i < 7)
			    buf [0] |= 1 << (i + 1);
			else
			    buf [1] |= 1 << (i - 7);
			continue;
		}

		/* can suspend if no ports are enabled; or if all all
		 * enabled ports are suspended AND remote wakeup is on.
		 */
		if (!(status & RH_PS_CCS))
			continue;
		if ((status & RH_PS_PSS) && ohci->hcd.remote_wakeup)
			continue;
		can_suspend = 0;
	}

#ifdef CONFIG_PM
	/* save power by suspending idle root hubs;
	 * INTR_RD wakes us when there's work
	 */
	if (can_suspend
			&& !changed
			&& !ohci->ed_rm_list
			&& ((OHCI_CTRL_HCFS | OHCI_SCHED_ENABLES)
					& ohci->hc_control)
				== OHCI_USB_OPER
			&& down_trylock (&hcd->self.root_hub->serialize) == 0
			) {
		ohci_vdbg (ohci, "autosuspend\n");
		(void) ohci_hub_suspend (&ohci->hcd);
		ohci->hcd.state = USB_STATE_RUNNING;
		up (&hcd->self.root_hub->serialize);
	}
#endif

	return changed ? length : 0;
}