2005-04-17 05:20:36 +07:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2001-2002 by David Brownell
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
|
|
* under the terms of the GNU General Public License as published by the
|
|
|
|
* Free Software Foundation; either version 2 of the License, or (at your
|
|
|
|
* option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful, but
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
|
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
|
|
* for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
|
|
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
*/
|
|
|
|
|
2008-10-30 04:25:50 +07:00
|
|
|
#ifndef __USB_CORE_HCD_H
|
|
|
|
#define __USB_CORE_HCD_H
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
#ifdef __KERNEL__
|
|
|
|
|
2007-10-11 03:27:07 +07:00
|
|
|
#include <linux/rwsem.h>
|
USB: HCD: support giveback of URB in tasklet context
This patch implements the mechanism of giveback of URB in
tasklet context, so that hardware interrupt handling time for
usb host controller can be saved much, and HCD interrupt handling
can be simplified.
Motivations:
1), on some arch(such as ARM), DMA mapping/unmapping is a bit
time-consuming, for example: when accessing usb mass storage
via EHCI on pandaboard, the common length of transfer buffer is 120KB,
the time consumed on DMA unmapping may reach hundreds of microseconds;
even on A15 based box, the time is still about scores of microseconds
2), on some arch, reading DMA coherent memoery is very time-consuming,
the most common example is usb video class driver[1]
3), driver's complete() callback may do much things which is driver
specific, so the time is consumed unnecessarily in hardware irq context.
4), running driver's complete() callback in hardware irq context causes
that host controller driver has to release its lock in interrupt handler,
so reacquiring the lock after return may busy wait a while and increase
interrupt handling time. More seriously, releasing the HCD lock makes
HCD becoming quite complicated to deal with introduced races.
So the patch proposes to run giveback of URB in tasklet context, then
time consumed in HCD irq handling doesn't depend on drivers' complete and
DMA mapping/unmapping any more, also we can simplify HCD since the HCD
lock isn't needed to be released during irq handling.
The patch should be reasonable and doable:
1), for drivers, they don't care if the complete() is called in hard irq
context or softirq context
2), the biggest change is the situation in which usb_submit_urb() is called
in complete() callback, so the introduced tasklet schedule delay might be a
con, but it shouldn't be a big deal:
- control/bulk asynchronous transfer isn't sensitive to schedule
delay
- the patch schedules giveback of periodic URBs using
tasklet_hi_schedule, so the introduced delay should be very
small
- for ISOC transfer, generally, drivers submit several URBs
concurrently to avoid interrupt delay, so it is OK with the
little schedule delay.
- for interrupt transfer, generally, drivers only submit one URB
at the same time, but interrupt transfer is often used in event
report, polling, ... situations, and a little delay should be OK.
Considered that HCDs may optimize on submitting URB in complete(), the
patch may cause the optimization not working, so introduces one flag to mark
if the HCD supports to run giveback URB in tasklet context. When all HCDs
are ready, the flag can be removed.
[1], http://marc.info/?t=136438111600010&r=1&w=2
Cc: Oliver Neukum <oliver@neukum.org>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Ming Lei <ming.lei@canonical.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-07-03 21:53:07 +07:00
|
|
|
#include <linux/interrupt.h>
|
2016-01-26 02:30:30 +07:00
|
|
|
#include <linux/idr.h>
|
2007-10-11 03:27:07 +07:00
|
|
|
|
2008-06-12 14:49:47 +07:00
|
|
|
#define MAX_TOPO_LEVEL 6
|
|
|
|
|
2005-04-17 05:20:36 +07:00
|
|
|
/* This file contains declarations of usbcore internals that are mostly
|
|
|
|
* used or exposed by Host Controller Drivers.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* USB Packet IDs (PIDs)
|
|
|
|
*/
|
2008-02-11 03:24:00 +07:00
|
|
|
#define USB_PID_EXT 0xf0 /* USB 2.0 LPM ECN */
|
2005-04-17 05:20:36 +07:00
|
|
|
#define USB_PID_OUT 0xe1
|
|
|
|
#define USB_PID_ACK 0xd2
|
|
|
|
#define USB_PID_DATA0 0xc3
|
|
|
|
#define USB_PID_PING 0xb4 /* USB 2.0 */
|
|
|
|
#define USB_PID_SOF 0xa5
|
|
|
|
#define USB_PID_NYET 0x96 /* USB 2.0 */
|
|
|
|
#define USB_PID_DATA2 0x87 /* USB 2.0 */
|
|
|
|
#define USB_PID_SPLIT 0x78 /* USB 2.0 */
|
|
|
|
#define USB_PID_IN 0x69
|
|
|
|
#define USB_PID_NAK 0x5a
|
|
|
|
#define USB_PID_DATA1 0x4b
|
|
|
|
#define USB_PID_PREAMBLE 0x3c /* Token mode */
|
|
|
|
#define USB_PID_ERR 0x3c /* USB 2.0: handshake mode */
|
|
|
|
#define USB_PID_SETUP 0x2d
|
|
|
|
#define USB_PID_STALL 0x1e
|
|
|
|
#define USB_PID_MDATA 0x0f /* USB 2.0 */
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* USB Host Controller Driver (usb_hcd) framework
|
|
|
|
*
|
|
|
|
* Since "struct usb_bus" is so thin, you can't share much code in it.
|
|
|
|
* This framework is a layer over that, and should be more sharable.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
|
|
|
USB: HCD: support giveback of URB in tasklet context
This patch implements the mechanism of giveback of URB in
tasklet context, so that hardware interrupt handling time for
usb host controller can be saved much, and HCD interrupt handling
can be simplified.
Motivations:
1), on some arch(such as ARM), DMA mapping/unmapping is a bit
time-consuming, for example: when accessing usb mass storage
via EHCI on pandaboard, the common length of transfer buffer is 120KB,
the time consumed on DMA unmapping may reach hundreds of microseconds;
even on A15 based box, the time is still about scores of microseconds
2), on some arch, reading DMA coherent memoery is very time-consuming,
the most common example is usb video class driver[1]
3), driver's complete() callback may do much things which is driver
specific, so the time is consumed unnecessarily in hardware irq context.
4), running driver's complete() callback in hardware irq context causes
that host controller driver has to release its lock in interrupt handler,
so reacquiring the lock after return may busy wait a while and increase
interrupt handling time. More seriously, releasing the HCD lock makes
HCD becoming quite complicated to deal with introduced races.
So the patch proposes to run giveback of URB in tasklet context, then
time consumed in HCD irq handling doesn't depend on drivers' complete and
DMA mapping/unmapping any more, also we can simplify HCD since the HCD
lock isn't needed to be released during irq handling.
The patch should be reasonable and doable:
1), for drivers, they don't care if the complete() is called in hard irq
context or softirq context
2), the biggest change is the situation in which usb_submit_urb() is called
in complete() callback, so the introduced tasklet schedule delay might be a
con, but it shouldn't be a big deal:
- control/bulk asynchronous transfer isn't sensitive to schedule
delay
- the patch schedules giveback of periodic URBs using
tasklet_hi_schedule, so the introduced delay should be very
small
- for ISOC transfer, generally, drivers submit several URBs
concurrently to avoid interrupt delay, so it is OK with the
little schedule delay.
- for interrupt transfer, generally, drivers only submit one URB
at the same time, but interrupt transfer is often used in event
report, polling, ... situations, and a little delay should be OK.
Considered that HCDs may optimize on submitting URB in complete(), the
patch may cause the optimization not working, so introduces one flag to mark
if the HCD supports to run giveback URB in tasklet context. When all HCDs
are ready, the flag can be removed.
[1], http://marc.info/?t=136438111600010&r=1&w=2
Cc: Oliver Neukum <oliver@neukum.org>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Ming Lei <ming.lei@canonical.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-07-03 21:53:07 +07:00
|
|
|
struct giveback_urb_bh {
|
|
|
|
bool running;
|
|
|
|
spinlock_t lock;
|
|
|
|
struct list_head head;
|
|
|
|
struct tasklet_struct bh;
|
2013-09-04 00:58:43 +07:00
|
|
|
struct usb_host_endpoint *completing_ep;
|
USB: HCD: support giveback of URB in tasklet context
This patch implements the mechanism of giveback of URB in
tasklet context, so that hardware interrupt handling time for
usb host controller can be saved much, and HCD interrupt handling
can be simplified.
Motivations:
1), on some arch(such as ARM), DMA mapping/unmapping is a bit
time-consuming, for example: when accessing usb mass storage
via EHCI on pandaboard, the common length of transfer buffer is 120KB,
the time consumed on DMA unmapping may reach hundreds of microseconds;
even on A15 based box, the time is still about scores of microseconds
2), on some arch, reading DMA coherent memoery is very time-consuming,
the most common example is usb video class driver[1]
3), driver's complete() callback may do much things which is driver
specific, so the time is consumed unnecessarily in hardware irq context.
4), running driver's complete() callback in hardware irq context causes
that host controller driver has to release its lock in interrupt handler,
so reacquiring the lock after return may busy wait a while and increase
interrupt handling time. More seriously, releasing the HCD lock makes
HCD becoming quite complicated to deal with introduced races.
So the patch proposes to run giveback of URB in tasklet context, then
time consumed in HCD irq handling doesn't depend on drivers' complete and
DMA mapping/unmapping any more, also we can simplify HCD since the HCD
lock isn't needed to be released during irq handling.
The patch should be reasonable and doable:
1), for drivers, they don't care if the complete() is called in hard irq
context or softirq context
2), the biggest change is the situation in which usb_submit_urb() is called
in complete() callback, so the introduced tasklet schedule delay might be a
con, but it shouldn't be a big deal:
- control/bulk asynchronous transfer isn't sensitive to schedule
delay
- the patch schedules giveback of periodic URBs using
tasklet_hi_schedule, so the introduced delay should be very
small
- for ISOC transfer, generally, drivers submit several URBs
concurrently to avoid interrupt delay, so it is OK with the
little schedule delay.
- for interrupt transfer, generally, drivers only submit one URB
at the same time, but interrupt transfer is often used in event
report, polling, ... situations, and a little delay should be OK.
Considered that HCDs may optimize on submitting URB in complete(), the
patch may cause the optimization not working, so introduces one flag to mark
if the HCD supports to run giveback URB in tasklet context. When all HCDs
are ready, the flag can be removed.
[1], http://marc.info/?t=136438111600010&r=1&w=2
Cc: Oliver Neukum <oliver@neukum.org>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Ming Lei <ming.lei@canonical.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-07-03 21:53:07 +07:00
|
|
|
};
|
|
|
|
|
2006-08-30 22:32:52 +07:00
|
|
|
struct usb_hcd {
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
/*
|
|
|
|
* housekeeping
|
|
|
|
*/
|
|
|
|
struct usb_bus self; /* hcd is-a bus */
|
2006-08-30 22:32:52 +07:00
|
|
|
struct kref kref; /* reference counter */
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
const char *product_desc; /* product/vendor string */
|
2010-12-03 05:45:18 +07:00
|
|
|
int speed; /* Speed for this roothub.
|
|
|
|
* May be different from
|
|
|
|
* hcd->driver->flags & HCD_MASK
|
|
|
|
*/
|
2005-04-17 05:20:36 +07:00
|
|
|
char irq_descr[24]; /* driver + bus # */
|
|
|
|
|
2005-04-22 02:56:37 +07:00
|
|
|
struct timer_list rh_timer; /* drives root-hub polling */
|
|
|
|
struct urb *status_urb; /* the current status urb */
|
2014-11-30 05:47:05 +07:00
|
|
|
#ifdef CONFIG_PM
|
2007-03-14 03:37:30 +07:00
|
|
|
struct work_struct wakeup_work; /* for remote wakeup */
|
|
|
|
#endif
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
/*
|
|
|
|
* hardware info/state
|
|
|
|
*/
|
|
|
|
const struct hc_driver *driver; /* hw-specific hooks */
|
[PATCH] USB: Fix USB suspend/resume crasher (#2)
This patch closes the IRQ race and makes various other OHCI & EHCI code
path safer vs. suspend/resume.
I've been able to (finally !) successfully suspend and resume various
Mac models, with or without USB mouse plugged, or plugging while asleep,
or unplugging while asleep etc... all without a crash.
Alan, please verify the UHCI bit I did, I only verified that it builds.
It's very simple so I wouldn't expect any issue there. If you aren't
confident, then just drop the hunks that change uhci-hcd.c
I also made the patch a little bit more "safer" by making sure the store
to the interrupt register that disables interrupts is not posted before
I set the flag and drop the spinlock.
Without this patch, you cannot reliably sleep/wakeup any recent Mac, and
I suspect PCs have some more sneaky issues too (they don't frankly crash
with machine checks because x86 tend to silently swallow PCI errors but
that won't last afaik, at least PCI Express will blow up in those
situations, but the USB code may still misbehave).
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2005-11-25 05:59:46 +07:00
|
|
|
|
2012-06-13 19:34:12 +07:00
|
|
|
/*
|
|
|
|
* OTG and some Host controllers need software interaction with phys;
|
|
|
|
* other external phys should be software-transparent
|
|
|
|
*/
|
2014-09-25 02:05:50 +07:00
|
|
|
struct usb_phy *usb_phy;
|
2014-09-25 02:09:44 +07:00
|
|
|
struct phy *phy;
|
2012-06-13 19:34:12 +07:00
|
|
|
|
2010-06-23 03:39:10 +07:00
|
|
|
/* Flags that need to be manipulated atomically because they can
|
|
|
|
* change while the host controller is running. Always use
|
|
|
|
* set_bit() or clear_bit() to change their values.
|
|
|
|
*/
|
[PATCH] USB: Fix USB suspend/resume crasher (#2)
This patch closes the IRQ race and makes various other OHCI & EHCI code
path safer vs. suspend/resume.
I've been able to (finally !) successfully suspend and resume various
Mac models, with or without USB mouse plugged, or plugging while asleep,
or unplugging while asleep etc... all without a crash.
Alan, please verify the UHCI bit I did, I only verified that it builds.
It's very simple so I wouldn't expect any issue there. If you aren't
confident, then just drop the hunks that change uhci-hcd.c
I also made the patch a little bit more "safer" by making sure the store
to the interrupt register that disables interrupts is not posted before
I set the flag and drop the spinlock.
Without this patch, you cannot reliably sleep/wakeup any recent Mac, and
I suspect PCs have some more sneaky issues too (they don't frankly crash
with machine checks because x86 tend to silently swallow PCI errors but
that won't last afaik, at least PCI Express will blow up in those
situations, but the USB code may still misbehave).
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2005-11-25 05:59:46 +07:00
|
|
|
unsigned long flags;
|
2010-06-23 03:39:10 +07:00
|
|
|
#define HCD_FLAG_HW_ACCESSIBLE 0 /* at full power */
|
|
|
|
#define HCD_FLAG_POLL_RH 2 /* poll for rh status? */
|
|
|
|
#define HCD_FLAG_POLL_PENDING 3 /* status has changed? */
|
2010-06-26 01:02:35 +07:00
|
|
|
#define HCD_FLAG_WAKEUP_PENDING 4 /* root hub is resuming? */
|
2011-03-07 23:11:52 +07:00
|
|
|
#define HCD_FLAG_RH_RUNNING 5 /* root hub is running? */
|
|
|
|
#define HCD_FLAG_DEAD 6 /* controller has died? */
|
2015-08-26 02:10:06 +07:00
|
|
|
#define HCD_FLAG_INTF_AUTHORIZED 7 /* authorize interfaces? */
|
2015-08-26 02:10:11 +07:00
|
|
|
#define HCD_FLAG_DEV_AUTHORIZED 8 /* authorize devices? */
|
2010-06-23 03:39:10 +07:00
|
|
|
|
|
|
|
/* The flags can be tested using these macros; they are likely to
|
|
|
|
* be slightly faster than test_bit().
|
|
|
|
*/
|
|
|
|
#define HCD_HW_ACCESSIBLE(hcd) ((hcd)->flags & (1U << HCD_FLAG_HW_ACCESSIBLE))
|
|
|
|
#define HCD_POLL_RH(hcd) ((hcd)->flags & (1U << HCD_FLAG_POLL_RH))
|
|
|
|
#define HCD_POLL_PENDING(hcd) ((hcd)->flags & (1U << HCD_FLAG_POLL_PENDING))
|
2010-06-26 01:02:35 +07:00
|
|
|
#define HCD_WAKEUP_PENDING(hcd) ((hcd)->flags & (1U << HCD_FLAG_WAKEUP_PENDING))
|
2011-03-07 23:11:52 +07:00
|
|
|
#define HCD_RH_RUNNING(hcd) ((hcd)->flags & (1U << HCD_FLAG_RH_RUNNING))
|
|
|
|
#define HCD_DEAD(hcd) ((hcd)->flags & (1U << HCD_FLAG_DEAD))
|
[PATCH] USB: Fix USB suspend/resume crasher (#2)
This patch closes the IRQ race and makes various other OHCI & EHCI code
path safer vs. suspend/resume.
I've been able to (finally !) successfully suspend and resume various
Mac models, with or without USB mouse plugged, or plugging while asleep,
or unplugging while asleep etc... all without a crash.
Alan, please verify the UHCI bit I did, I only verified that it builds.
It's very simple so I wouldn't expect any issue there. If you aren't
confident, then just drop the hunks that change uhci-hcd.c
I also made the patch a little bit more "safer" by making sure the store
to the interrupt register that disables interrupts is not posted before
I set the flag and drop the spinlock.
Without this patch, you cannot reliably sleep/wakeup any recent Mac, and
I suspect PCs have some more sneaky issues too (they don't frankly crash
with machine checks because x86 tend to silently swallow PCI errors but
that won't last afaik, at least PCI Express will blow up in those
situations, but the USB code may still misbehave).
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2005-11-25 05:59:46 +07:00
|
|
|
|
2015-08-26 02:10:06 +07:00
|
|
|
/*
|
|
|
|
* Specifies if interfaces are authorized by default
|
|
|
|
* or they require explicit user space authorization; this bit is
|
|
|
|
* settable through /sys/class/usb_host/X/interface_authorized_default
|
|
|
|
*/
|
|
|
|
#define HCD_INTF_AUTHORIZED(hcd) \
|
|
|
|
((hcd)->flags & (1U << HCD_FLAG_INTF_AUTHORIZED))
|
|
|
|
|
2015-08-26 02:10:11 +07:00
|
|
|
/*
|
|
|
|
* Specifies if devices are authorized by default
|
|
|
|
* or they require explicit user space authorization; this bit is
|
|
|
|
* settable through /sys/class/usb_host/X/authorized_default
|
|
|
|
*/
|
|
|
|
#define HCD_DEV_AUTHORIZED(hcd) \
|
|
|
|
((hcd)->flags & (1U << HCD_FLAG_DEV_AUTHORIZED))
|
|
|
|
|
2010-06-23 03:39:10 +07:00
|
|
|
/* Flags that get set only during HCD registration or removal. */
|
2005-04-17 05:20:36 +07:00
|
|
|
unsigned rh_registered:1;/* is root hub registered? */
|
2010-06-10 04:34:17 +07:00
|
|
|
unsigned rh_pollable:1; /* may we poll the root hub? */
|
2010-12-27 16:39:02 +07:00
|
|
|
unsigned msix_enabled:1; /* driver has MSI-X enabled? */
|
2017-05-17 22:32:02 +07:00
|
|
|
unsigned msi_enabled:1; /* driver has MSI enabled? */
|
2013-12-04 04:42:21 +07:00
|
|
|
unsigned remove_phy:1; /* auto-remove USB phy */
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2005-04-22 02:56:37 +07:00
|
|
|
/* The next flag is a stopgap, to be removed when all the HCDs
|
|
|
|
* support the new root-hub polling mechanism. */
|
|
|
|
unsigned uses_new_polling:1;
|
2006-08-26 09:35:29 +07:00
|
|
|
unsigned wireless:1; /* Wireless USB HCD */
|
2008-04-04 05:02:56 +07:00
|
|
|
unsigned has_tt:1; /* Integrated TT in root hub */
|
2013-09-16 22:47:28 +07:00
|
|
|
unsigned amd_resume_bug:1; /* AMD remote wakeup quirk */
|
2014-02-12 02:36:04 +07:00
|
|
|
unsigned can_do_streams:1; /* HC supports streams */
|
2014-08-19 08:51:52 +07:00
|
|
|
unsigned tpl_support:1; /* OTG & EH TPL support */
|
2015-01-30 03:05:04 +07:00
|
|
|
unsigned cant_recv_wakeups:1;
|
|
|
|
/* wakeup requests from downstream aren't received */
|
2005-04-22 02:56:37 +07:00
|
|
|
|
2012-02-29 21:46:23 +07:00
|
|
|
unsigned int irq; /* irq allocated */
|
2005-04-17 05:20:36 +07:00
|
|
|
void __iomem *regs; /* device memory/io */
|
2012-08-16 19:54:19 +07:00
|
|
|
resource_size_t rsrc_start; /* memory/io resource start */
|
|
|
|
resource_size_t rsrc_len; /* memory/io resource length */
|
2005-04-25 22:18:32 +07:00
|
|
|
unsigned power_budget; /* in mA, 0 = no limit */
|
2005-04-17 05:20:36 +07:00
|
|
|
|
USB: HCD: support giveback of URB in tasklet context
This patch implements the mechanism of giveback of URB in
tasklet context, so that hardware interrupt handling time for
usb host controller can be saved much, and HCD interrupt handling
can be simplified.
Motivations:
1), on some arch(such as ARM), DMA mapping/unmapping is a bit
time-consuming, for example: when accessing usb mass storage
via EHCI on pandaboard, the common length of transfer buffer is 120KB,
the time consumed on DMA unmapping may reach hundreds of microseconds;
even on A15 based box, the time is still about scores of microseconds
2), on some arch, reading DMA coherent memoery is very time-consuming,
the most common example is usb video class driver[1]
3), driver's complete() callback may do much things which is driver
specific, so the time is consumed unnecessarily in hardware irq context.
4), running driver's complete() callback in hardware irq context causes
that host controller driver has to release its lock in interrupt handler,
so reacquiring the lock after return may busy wait a while and increase
interrupt handling time. More seriously, releasing the HCD lock makes
HCD becoming quite complicated to deal with introduced races.
So the patch proposes to run giveback of URB in tasklet context, then
time consumed in HCD irq handling doesn't depend on drivers' complete and
DMA mapping/unmapping any more, also we can simplify HCD since the HCD
lock isn't needed to be released during irq handling.
The patch should be reasonable and doable:
1), for drivers, they don't care if the complete() is called in hard irq
context or softirq context
2), the biggest change is the situation in which usb_submit_urb() is called
in complete() callback, so the introduced tasklet schedule delay might be a
con, but it shouldn't be a big deal:
- control/bulk asynchronous transfer isn't sensitive to schedule
delay
- the patch schedules giveback of periodic URBs using
tasklet_hi_schedule, so the introduced delay should be very
small
- for ISOC transfer, generally, drivers submit several URBs
concurrently to avoid interrupt delay, so it is OK with the
little schedule delay.
- for interrupt transfer, generally, drivers only submit one URB
at the same time, but interrupt transfer is often used in event
report, polling, ... situations, and a little delay should be OK.
Considered that HCDs may optimize on submitting URB in complete(), the
patch may cause the optimization not working, so introduces one flag to mark
if the HCD supports to run giveback URB in tasklet context. When all HCDs
are ready, the flag can be removed.
[1], http://marc.info/?t=136438111600010&r=1&w=2
Cc: Oliver Neukum <oliver@neukum.org>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Ming Lei <ming.lei@canonical.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-07-03 21:53:07 +07:00
|
|
|
struct giveback_urb_bh high_prio_bh;
|
|
|
|
struct giveback_urb_bh low_prio_bh;
|
|
|
|
|
USB: Check bandwidth when switching alt settings.
Make the USB core check the bandwidth when switching from one
interface alternate setting to another. Also check the bandwidth
when resetting a configuration (so that alt setting 0 is used). If
this check fails, the device's state is unchanged. If the device
refuses the new alt setting, re-instate the old alt setting in the
host controller hardware.
If a USB device doesn't have an alternate interface setting 0, install
the first alt setting in its descriptors when a new configuration is
requested, or the device is reset.
Add a mutex per root hub to protect bandwidth operations:
adding/reseting/changing configurations, and changing alternate interface
settings. We want to ensure that the xHCI host controller and the USB
device are set up for the same configurations and alternate settings.
There are two (possibly three) steps to do this:
1. The host controller needs to check that bandwidth is available for a
different setting, by issuing and waiting for a configure endpoint
command.
2. Once that returns successfully, a control message is sent to the
device.
3. If that fails, the host controller must be notified through another
configure endpoint command.
The mutex is used to make these three operations seem atomic, to prevent
another driver from using more bandwidth for a different device while
we're in the middle of these operations.
While we're touching the bandwidth code, rename usb_hcd_check_bandwidth()
to usb_hcd_alloc_bandwidth(). This function does more than just check
that the bandwidth change won't exceed the bus bandwidth; it actually
changes the bandwidth configuration in the xHCI host controller.
Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2009-12-04 00:44:36 +07:00
|
|
|
/* bandwidth_mutex should be taken before adding or removing
|
|
|
|
* any new bus bandwidth constraints:
|
|
|
|
* 1. Before adding a configuration for a new device.
|
|
|
|
* 2. Before removing the configuration to put the device into
|
|
|
|
* the addressed state.
|
|
|
|
* 3. Before selecting a different configuration.
|
|
|
|
* 4. Before selecting an alternate interface setting.
|
|
|
|
*
|
|
|
|
* bandwidth_mutex should be dropped after a successful control message
|
|
|
|
* to the device, or resetting the bandwidth after a failed attempt.
|
|
|
|
*/
|
2016-04-25 19:48:38 +07:00
|
|
|
struct mutex *address0_mutex;
|
2010-10-15 22:55:24 +07:00
|
|
|
struct mutex *bandwidth_mutex;
|
usb: Make core allocate resources per PCI-device.
Introduce the notion of a PCI device that may be associated with more than
one USB host controller driver (struct usb_hcd). This patch is the start
of the work to separate the xHCI host controller into two roothubs: a USB
3.0 roothub with SuperSpeed-only ports, and a USB 2.0 roothub with
HS/FS/LS ports.
One usb_hcd structure is designated to be the "primary HCD", and a pointer
is added to the usb_hcd structure to keep track of that. A new function
call, usb_hcd_is_primary_hcd() is added to check whether the USB hcd is
marked as the primary HCD (or if it is not part of a roothub pair). To
allow the USB core and xHCI driver to access either roothub in a pair, a
"shared_hcd" pointer is added to the usb_hcd structure.
Add a new function, usb_create_shared_hcd(), that does roothub allocation
for paired roothubs. It will act just like usb_create_hcd() did if the
primary_hcd pointer argument is NULL. If it is passed a non-NULL
primary_hcd pointer, it sets usb_hcd->shared_hcd and usb_hcd->primary_hcd
fields. It will also skip the bandwidth_mutex allocation, and set the
secondary hcd's bandwidth_mutex pointer to the primary HCD's mutex.
IRQs are only allocated once for the primary roothub.
Introduce a new usb_hcd driver flag that indicates the host controller
driver wants to create two roothubs. If the HCD_SHARED flag is set, then
the USB core PCI probe methods will allocate a second roothub, and make
sure that second roothub gets freed during rmmod and in initialization
error paths.
When usb_hc_died() is called with the primary HCD, make sure that any
roothubs that share that host controller are also marked as being dead.
Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
2010-10-29 05:40:26 +07:00
|
|
|
struct usb_hcd *shared_hcd;
|
|
|
|
struct usb_hcd *primary_hcd;
|
USB: Check bandwidth when switching alt settings.
Make the USB core check the bandwidth when switching from one
interface alternate setting to another. Also check the bandwidth
when resetting a configuration (so that alt setting 0 is used). If
this check fails, the device's state is unchanged. If the device
refuses the new alt setting, re-instate the old alt setting in the
host controller hardware.
If a USB device doesn't have an alternate interface setting 0, install
the first alt setting in its descriptors when a new configuration is
requested, or the device is reset.
Add a mutex per root hub to protect bandwidth operations:
adding/reseting/changing configurations, and changing alternate interface
settings. We want to ensure that the xHCI host controller and the USB
device are set up for the same configurations and alternate settings.
There are two (possibly three) steps to do this:
1. The host controller needs to check that bandwidth is available for a
different setting, by issuing and waiting for a configure endpoint
command.
2. Once that returns successfully, a control message is sent to the
device.
3. If that fails, the host controller must be notified through another
configure endpoint command.
The mutex is used to make these three operations seem atomic, to prevent
another driver from using more bandwidth for a different device while
we're in the middle of these operations.
While we're touching the bandwidth code, rename usb_hcd_check_bandwidth()
to usb_hcd_alloc_bandwidth(). This function does more than just check
that the bandwidth change won't exceed the bus bandwidth; it actually
changes the bandwidth configuration in the xHCI host controller.
Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2009-12-04 00:44:36 +07:00
|
|
|
|
|
|
|
|
2005-04-17 05:20:36 +07:00
|
|
|
#define HCD_BUFFER_POOLS 4
|
2010-05-18 00:58:12 +07:00
|
|
|
struct dma_pool *pool[HCD_BUFFER_POOLS];
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
int state;
|
|
|
|
# define __ACTIVE 0x01
|
|
|
|
# define __SUSPEND 0x04
|
|
|
|
# define __TRANSIENT 0x80
|
|
|
|
|
|
|
|
# define HC_STATE_HALT 0
|
|
|
|
# define HC_STATE_RUNNING (__ACTIVE)
|
|
|
|
# define HC_STATE_QUIESCING (__SUSPEND|__TRANSIENT|__ACTIVE)
|
|
|
|
# define HC_STATE_RESUMING (__SUSPEND|__TRANSIENT)
|
|
|
|
# define HC_STATE_SUSPENDED (__SUSPEND)
|
|
|
|
|
|
|
|
#define HC_IS_RUNNING(state) ((state) & __ACTIVE)
|
|
|
|
#define HC_IS_SUSPENDED(state) ((state) & __SUSPEND)
|
|
|
|
|
|
|
|
/* more shared queuing code would be good; it should support
|
|
|
|
* smarter scheduling, handle transaction translators, etc;
|
2008-01-31 06:21:33 +07:00
|
|
|
* input size of periodic table to an interrupt scheduler.
|
2005-04-17 05:20:36 +07:00
|
|
|
* (ohci 32, uhci 1024, ehci 256/512/1024).
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* The HC driver's private data is stored at the end of
|
|
|
|
* this structure.
|
|
|
|
*/
|
|
|
|
unsigned long hcd_priv[0]
|
2011-10-10 19:38:27 +07:00
|
|
|
__attribute__ ((aligned(sizeof(s64))));
|
2005-04-17 05:20:36 +07:00
|
|
|
};
|
|
|
|
|
|
|
|
/* 2.4 does this a bit differently ... */
|
2008-01-31 06:21:33 +07:00
|
|
|
static inline struct usb_bus *hcd_to_bus(struct usb_hcd *hcd)
|
2005-04-17 05:20:36 +07:00
|
|
|
{
|
|
|
|
return &hcd->self;
|
|
|
|
}
|
|
|
|
|
2008-01-31 06:21:33 +07:00
|
|
|
static inline struct usb_hcd *bus_to_hcd(struct usb_bus *bus)
|
2006-08-30 22:32:52 +07:00
|
|
|
{
|
|
|
|
return container_of(bus, struct usb_hcd, self);
|
|
|
|
}
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
struct hcd_timeout { /* timeouts we allocate */
|
|
|
|
struct list_head timeout_list;
|
|
|
|
struct timer_list timer;
|
|
|
|
};
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
|
|
struct hc_driver {
|
|
|
|
const char *description; /* "ehci-hcd" etc */
|
|
|
|
const char *product_desc; /* product/vendor string */
|
|
|
|
size_t hcd_priv_size; /* size of private data */
|
|
|
|
|
|
|
|
/* irq handler */
|
IRQ: Maintain regs pointer globally rather than passing to IRQ handlers
Maintain a per-CPU global "struct pt_regs *" variable which can be used instead
of passing regs around manually through all ~1800 interrupt handlers in the
Linux kernel.
The regs pointer is used in few places, but it potentially costs both stack
space and code to pass it around. On the FRV arch, removing the regs parameter
from all the genirq function results in a 20% speed up of the IRQ exit path
(ie: from leaving timer_interrupt() to leaving do_IRQ()).
Where appropriate, an arch may override the generic storage facility and do
something different with the variable. On FRV, for instance, the address is
maintained in GR28 at all times inside the kernel as part of general exception
handling.
Having looked over the code, it appears that the parameter may be handed down
through up to twenty or so layers of functions. Consider a USB character
device attached to a USB hub, attached to a USB controller that posts its
interrupts through a cascaded auxiliary interrupt controller. A character
device driver may want to pass regs to the sysrq handler through the input
layer which adds another few layers of parameter passing.
I've build this code with allyesconfig for x86_64 and i386. I've runtested the
main part of the code on FRV and i386, though I can't test most of the drivers.
I've also done partial conversion for powerpc and MIPS - these at least compile
with minimal configurations.
This will affect all archs. Mostly the changes should be relatively easy.
Take do_IRQ(), store the regs pointer at the beginning, saving the old one:
struct pt_regs *old_regs = set_irq_regs(regs);
And put the old one back at the end:
set_irq_regs(old_regs);
Don't pass regs through to generic_handle_irq() or __do_IRQ().
In timer_interrupt(), this sort of change will be necessary:
- update_process_times(user_mode(regs));
- profile_tick(CPU_PROFILING, regs);
+ update_process_times(user_mode(get_irq_regs()));
+ profile_tick(CPU_PROFILING);
I'd like to move update_process_times()'s use of get_irq_regs() into itself,
except that i386, alone of the archs, uses something other than user_mode().
Some notes on the interrupt handling in the drivers:
(*) input_dev() is now gone entirely. The regs pointer is no longer stored in
the input_dev struct.
(*) finish_unlinks() in drivers/usb/host/ohci-q.c needs checking. It does
something different depending on whether it's been supplied with a regs
pointer or not.
(*) Various IRQ handler function pointers have been moved to type
irq_handler_t.
Signed-Off-By: David Howells <dhowells@redhat.com>
(cherry picked from 1b16e7ac850969f38b375e511e3fa2f474a33867 commit)
2006-10-05 20:55:46 +07:00
|
|
|
irqreturn_t (*irq) (struct usb_hcd *hcd);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
int flags;
|
|
|
|
#define HCD_MEMORY 0x0001 /* HC regs use memory (else I/O) */
|
2008-01-23 13:58:35 +07:00
|
|
|
#define HCD_LOCAL_MEM 0x0002 /* HC needs local memory */
|
usb: Make core allocate resources per PCI-device.
Introduce the notion of a PCI device that may be associated with more than
one USB host controller driver (struct usb_hcd). This patch is the start
of the work to separate the xHCI host controller into two roothubs: a USB
3.0 roothub with SuperSpeed-only ports, and a USB 2.0 roothub with
HS/FS/LS ports.
One usb_hcd structure is designated to be the "primary HCD", and a pointer
is added to the usb_hcd structure to keep track of that. A new function
call, usb_hcd_is_primary_hcd() is added to check whether the USB hcd is
marked as the primary HCD (or if it is not part of a roothub pair). To
allow the USB core and xHCI driver to access either roothub in a pair, a
"shared_hcd" pointer is added to the usb_hcd structure.
Add a new function, usb_create_shared_hcd(), that does roothub allocation
for paired roothubs. It will act just like usb_create_hcd() did if the
primary_hcd pointer argument is NULL. If it is passed a non-NULL
primary_hcd pointer, it sets usb_hcd->shared_hcd and usb_hcd->primary_hcd
fields. It will also skip the bandwidth_mutex allocation, and set the
secondary hcd's bandwidth_mutex pointer to the primary HCD's mutex.
IRQs are only allocated once for the primary roothub.
Introduce a new usb_hcd driver flag that indicates the host controller
driver wants to create two roothubs. If the HCD_SHARED flag is set, then
the USB core PCI probe methods will allocate a second roothub, and make
sure that second roothub gets freed during rmmod and in initialization
error paths.
When usb_hc_died() is called with the primary HCD, make sure that any
roothubs that share that host controller are also marked as being dead.
Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
2010-10-29 05:40:26 +07:00
|
|
|
#define HCD_SHARED 0x0004 /* Two (or more) usb_hcds share HW */
|
2005-04-17 05:20:36 +07:00
|
|
|
#define HCD_USB11 0x0010 /* USB 1.1 */
|
|
|
|
#define HCD_USB2 0x0020 /* USB 2.0 */
|
2013-06-01 02:16:13 +07:00
|
|
|
#define HCD_USB25 0x0030 /* Wireless USB 1.0 (USB 2.5)*/
|
2009-04-28 09:52:28 +07:00
|
|
|
#define HCD_USB3 0x0040 /* USB 3.0 */
|
2015-10-01 22:40:37 +07:00
|
|
|
#define HCD_USB31 0x0050 /* USB 3.1 */
|
2009-04-28 09:54:10 +07:00
|
|
|
#define HCD_MASK 0x0070
|
USB: HCD: support giveback of URB in tasklet context
This patch implements the mechanism of giveback of URB in
tasklet context, so that hardware interrupt handling time for
usb host controller can be saved much, and HCD interrupt handling
can be simplified.
Motivations:
1), on some arch(such as ARM), DMA mapping/unmapping is a bit
time-consuming, for example: when accessing usb mass storage
via EHCI on pandaboard, the common length of transfer buffer is 120KB,
the time consumed on DMA unmapping may reach hundreds of microseconds;
even on A15 based box, the time is still about scores of microseconds
2), on some arch, reading DMA coherent memoery is very time-consuming,
the most common example is usb video class driver[1]
3), driver's complete() callback may do much things which is driver
specific, so the time is consumed unnecessarily in hardware irq context.
4), running driver's complete() callback in hardware irq context causes
that host controller driver has to release its lock in interrupt handler,
so reacquiring the lock after return may busy wait a while and increase
interrupt handling time. More seriously, releasing the HCD lock makes
HCD becoming quite complicated to deal with introduced races.
So the patch proposes to run giveback of URB in tasklet context, then
time consumed in HCD irq handling doesn't depend on drivers' complete and
DMA mapping/unmapping any more, also we can simplify HCD since the HCD
lock isn't needed to be released during irq handling.
The patch should be reasonable and doable:
1), for drivers, they don't care if the complete() is called in hard irq
context or softirq context
2), the biggest change is the situation in which usb_submit_urb() is called
in complete() callback, so the introduced tasklet schedule delay might be a
con, but it shouldn't be a big deal:
- control/bulk asynchronous transfer isn't sensitive to schedule
delay
- the patch schedules giveback of periodic URBs using
tasklet_hi_schedule, so the introduced delay should be very
small
- for ISOC transfer, generally, drivers submit several URBs
concurrently to avoid interrupt delay, so it is OK with the
little schedule delay.
- for interrupt transfer, generally, drivers only submit one URB
at the same time, but interrupt transfer is often used in event
report, polling, ... situations, and a little delay should be OK.
Considered that HCDs may optimize on submitting URB in complete(), the
patch may cause the optimization not working, so introduces one flag to mark
if the HCD supports to run giveback URB in tasklet context. When all HCDs
are ready, the flag can be removed.
[1], http://marc.info/?t=136438111600010&r=1&w=2
Cc: Oliver Neukum <oliver@neukum.org>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Ming Lei <ming.lei@canonical.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-07-03 21:53:07 +07:00
|
|
|
#define HCD_BH 0x0100 /* URB complete in BH context */
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
/* called to init HCD and root hub */
|
|
|
|
int (*reset) (struct usb_hcd *hcd);
|
|
|
|
int (*start) (struct usb_hcd *hcd);
|
|
|
|
|
|
|
|
/* NOTE: these suspend/resume calls relate to the HC as
|
2005-09-23 12:38:16 +07:00
|
|
|
* a whole, not just the root hub; they're for PCI bus glue.
|
2005-04-17 05:20:36 +07:00
|
|
|
*/
|
2005-09-23 12:38:16 +07:00
|
|
|
/* called after suspending the hub, before entering D3 etc */
|
2010-06-26 01:02:14 +07:00
|
|
|
int (*pci_suspend)(struct usb_hcd *hcd, bool do_wakeup);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2005-09-23 12:38:16 +07:00
|
|
|
/* called after entering D0 (etc), before resuming the hub */
|
2009-04-28 00:33:41 +07:00
|
|
|
int (*pci_resume)(struct usb_hcd *hcd, bool hibernated);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
/* cleanly make HCD stop writing memory and doing I/O */
|
|
|
|
void (*stop) (struct usb_hcd *hcd);
|
|
|
|
|
USB: Properly unregister reboot notifier in case of failure in ehci hcd
If some problem occurs during ehci startup, for instance, request_irq fails,
echi hcd driver tries it best to cleanup, but fails to unregister reboot
notifier, which in turn leads to crash on reboot/poweroff.
The following patch resolves this problem by not using reboot notifiers
anymore, but instead making ehci/ohci driver get its own shutdown method. For
PCI, it is done through pci glue, for everything else through platform driver
glue.
One downside: sa1111 does not use platform driver stuff, and does not have its
own shutdown hook, so no 'shutdown' is called for it now. I'm not sure if it
is really necessary on that platform, though.
Signed-off-by: Aleks Gorelov <dared1st@yahoo.com>
Cc: Alan Stern <stern@rowland.harvard.edu>
Cc: David Brownell <david-b@pacbell.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2006-08-09 07:24:08 +07:00
|
|
|
/* shutdown HCD */
|
|
|
|
void (*shutdown) (struct usb_hcd *hcd);
|
|
|
|
|
2005-04-17 05:20:36 +07:00
|
|
|
/* return current frame number */
|
|
|
|
int (*get_frame_number) (struct usb_hcd *hcd);
|
|
|
|
|
|
|
|
/* manage i/o requests, device state */
|
2007-08-08 22:48:02 +07:00
|
|
|
int (*urb_enqueue)(struct usb_hcd *hcd,
|
|
|
|
struct urb *urb, gfp_t mem_flags);
|
|
|
|
int (*urb_dequeue)(struct usb_hcd *hcd,
|
|
|
|
struct urb *urb, int status);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2011-01-27 10:06:48 +07:00
|
|
|
/*
|
|
|
|
* (optional) these hooks allow an HCD to override the default DMA
|
|
|
|
* mapping and unmapping routines. In general, they shouldn't be
|
|
|
|
* necessary unless the host controller has special DMA requirements,
|
|
|
|
* such as alignment contraints. If these are not specified, the
|
|
|
|
* general usb_hcd_(un)?map_urb_for_dma functions will be used instead
|
|
|
|
* (and it may be a good idea to call these functions in your HCD
|
|
|
|
* implementation)
|
|
|
|
*/
|
|
|
|
int (*map_urb_for_dma)(struct usb_hcd *hcd, struct urb *urb,
|
|
|
|
gfp_t mem_flags);
|
|
|
|
void (*unmap_urb_for_dma)(struct usb_hcd *hcd, struct urb *urb);
|
|
|
|
|
2005-04-17 05:20:36 +07:00
|
|
|
/* hw synch, freeing endpoint resources that urb_dequeue can't */
|
2010-05-18 00:58:12 +07:00
|
|
|
void (*endpoint_disable)(struct usb_hcd *hcd,
|
2005-04-17 05:20:36 +07:00
|
|
|
struct usb_host_endpoint *ep);
|
|
|
|
|
2009-04-09 00:36:28 +07:00
|
|
|
/* (optional) reset any endpoint state such as sequence number
|
|
|
|
and current window */
|
2010-05-18 00:58:12 +07:00
|
|
|
void (*endpoint_reset)(struct usb_hcd *hcd,
|
2009-04-09 00:36:28 +07:00
|
|
|
struct usb_host_endpoint *ep);
|
|
|
|
|
2005-04-17 05:20:36 +07:00
|
|
|
/* root hub support */
|
2008-01-31 06:21:33 +07:00
|
|
|
int (*hub_status_data) (struct usb_hcd *hcd, char *buf);
|
|
|
|
int (*hub_control) (struct usb_hcd *hcd,
|
2005-04-17 05:20:36 +07:00
|
|
|
u16 typeReq, u16 wValue, u16 wIndex,
|
|
|
|
char *buf, u16 wLength);
|
2008-01-31 06:21:33 +07:00
|
|
|
int (*bus_suspend)(struct usb_hcd *);
|
|
|
|
int (*bus_resume)(struct usb_hcd *);
|
|
|
|
int (*start_port_reset)(struct usb_hcd *, unsigned port_num);
|
2007-11-22 03:28:14 +07:00
|
|
|
|
|
|
|
/* force handover of high-speed port to full-speed companion */
|
2008-01-31 06:21:33 +07:00
|
|
|
void (*relinquish_port)(struct usb_hcd *, int);
|
2008-05-21 03:58:29 +07:00
|
|
|
/* has a port been handed over to a companion? */
|
|
|
|
int (*port_handed_over)(struct usb_hcd *, int);
|
2009-04-28 09:57:26 +07:00
|
|
|
|
2009-06-29 21:43:32 +07:00
|
|
|
/* CLEAR_TT_BUFFER completion callback */
|
|
|
|
void (*clear_tt_buffer_complete)(struct usb_hcd *,
|
|
|
|
struct usb_host_endpoint *);
|
|
|
|
|
2009-04-28 09:57:26 +07:00
|
|
|
/* xHCI specific functions */
|
|
|
|
/* Called by usb_alloc_dev to alloc HC device structures */
|
|
|
|
int (*alloc_dev)(struct usb_hcd *, struct usb_device *);
|
2010-01-10 16:15:03 +07:00
|
|
|
/* Called by usb_disconnect to free HC device structures */
|
2009-04-28 09:57:26 +07:00
|
|
|
void (*free_dev)(struct usb_hcd *, struct usb_device *);
|
2010-04-06 00:55:58 +07:00
|
|
|
/* Change a group of bulk endpoints to support multiple stream IDs */
|
|
|
|
int (*alloc_streams)(struct usb_hcd *hcd, struct usb_device *udev,
|
|
|
|
struct usb_host_endpoint **eps, unsigned int num_eps,
|
|
|
|
unsigned int num_streams, gfp_t mem_flags);
|
|
|
|
/* Reverts a group of bulk endpoints back to not using stream IDs.
|
|
|
|
* Can fail if we run out of memory.
|
|
|
|
*/
|
|
|
|
int (*free_streams)(struct usb_hcd *hcd, struct usb_device *udev,
|
|
|
|
struct usb_host_endpoint **eps, unsigned int num_eps,
|
|
|
|
gfp_t mem_flags);
|
USB: Support for bandwidth allocation.
Originally, the USB core had no support for allocating bandwidth when a
particular configuration or alternate setting for an interface was
selected. Instead, the device driver's URB submission would fail if
there was not enough bandwidth for a periodic endpoint. Drivers could
work around this, by using the scatter-gather list API to guarantee
bandwidth.
This patch adds host controller API to allow the USB core to allocate or
deallocate bandwidth for an endpoint. Endpoints are added to or dropped
from a copy of the current schedule by calling add_endpoint() or
drop_endpoint(), and then the schedule is atomically evaluated with a
call to check_bandwidth(). This allows all the endpoints for a new
configuration or alternate setting to be added at the same time that the
endpoints from the old configuration or alt setting are dropped.
Endpoints must be added to the schedule before any URBs are submitted to
them. The HCD must be allowed to reject a new configuration or alt
setting before the control transfer is sent to the device requesting the
change. It may reject the change because there is not enough bandwidth,
not enough internal resources (such as memory on an embedded host
controller), or perhaps even for security reasons in a virtualized
environment.
If the call to check_bandwidth() fails, the USB core must call
reset_bandwidth(). This causes the schedule to be reverted back to the
state it was in just after the last successful check_bandwidth() call.
If the call succeeds, the host controller driver (and hardware) will have
changed its internal state to match the new configuration or alternate
setting. The USB core can then issue a control transfer to the device to
change the configuration or alt setting. This allows the core to test new
configurations or alternate settings before unbinding drivers bound to
interfaces in the old configuration.
WIP:
The USB core must add endpoints from all interfaces in a configuration
to the schedule, because a driver may claim that interface at any time.
A slight optimization might be to add the endpoints to the schedule once
a driver claims that interface. FIXME
This patch does not cover changing alternate settings, but it does
handle a configuration change or de-configuration. FIXME
The code for managing the schedule is currently HCD specific. A generic
scheduling algorithm could be added for host controllers without
built-in scheduling support. For now, if a host controller does not
define the check_bandwidth() function, the call to
usb_hcd_check_bandwidth() will always succeed.
Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2009-04-28 09:58:26 +07:00
|
|
|
|
|
|
|
/* Bandwidth computation functions */
|
|
|
|
/* Note that add_endpoint() can only be called once per endpoint before
|
|
|
|
* check_bandwidth() or reset_bandwidth() must be called.
|
|
|
|
* drop_endpoint() can only be called once per endpoint also.
|
2010-05-18 00:58:12 +07:00
|
|
|
* A call to xhci_drop_endpoint() followed by a call to
|
|
|
|
* xhci_add_endpoint() will add the endpoint to the schedule with
|
|
|
|
* possibly new parameters denoted by a different endpoint descriptor
|
|
|
|
* in usb_host_endpoint. A call to xhci_add_endpoint() followed by a
|
|
|
|
* call to xhci_drop_endpoint() is not allowed.
|
USB: Support for bandwidth allocation.
Originally, the USB core had no support for allocating bandwidth when a
particular configuration or alternate setting for an interface was
selected. Instead, the device driver's URB submission would fail if
there was not enough bandwidth for a periodic endpoint. Drivers could
work around this, by using the scatter-gather list API to guarantee
bandwidth.
This patch adds host controller API to allow the USB core to allocate or
deallocate bandwidth for an endpoint. Endpoints are added to or dropped
from a copy of the current schedule by calling add_endpoint() or
drop_endpoint(), and then the schedule is atomically evaluated with a
call to check_bandwidth(). This allows all the endpoints for a new
configuration or alternate setting to be added at the same time that the
endpoints from the old configuration or alt setting are dropped.
Endpoints must be added to the schedule before any URBs are submitted to
them. The HCD must be allowed to reject a new configuration or alt
setting before the control transfer is sent to the device requesting the
change. It may reject the change because there is not enough bandwidth,
not enough internal resources (such as memory on an embedded host
controller), or perhaps even for security reasons in a virtualized
environment.
If the call to check_bandwidth() fails, the USB core must call
reset_bandwidth(). This causes the schedule to be reverted back to the
state it was in just after the last successful check_bandwidth() call.
If the call succeeds, the host controller driver (and hardware) will have
changed its internal state to match the new configuration or alternate
setting. The USB core can then issue a control transfer to the device to
change the configuration or alt setting. This allows the core to test new
configurations or alternate settings before unbinding drivers bound to
interfaces in the old configuration.
WIP:
The USB core must add endpoints from all interfaces in a configuration
to the schedule, because a driver may claim that interface at any time.
A slight optimization might be to add the endpoints to the schedule once
a driver claims that interface. FIXME
This patch does not cover changing alternate settings, but it does
handle a configuration change or de-configuration. FIXME
The code for managing the schedule is currently HCD specific. A generic
scheduling algorithm could be added for host controllers without
built-in scheduling support. For now, if a host controller does not
define the check_bandwidth() function, the call to
usb_hcd_check_bandwidth() will always succeed.
Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2009-04-28 09:58:26 +07:00
|
|
|
*/
|
|
|
|
/* Allocate endpoint resources and add them to a new schedule */
|
2010-05-18 00:58:12 +07:00
|
|
|
int (*add_endpoint)(struct usb_hcd *, struct usb_device *,
|
|
|
|
struct usb_host_endpoint *);
|
USB: Support for bandwidth allocation.
Originally, the USB core had no support for allocating bandwidth when a
particular configuration or alternate setting for an interface was
selected. Instead, the device driver's URB submission would fail if
there was not enough bandwidth for a periodic endpoint. Drivers could
work around this, by using the scatter-gather list API to guarantee
bandwidth.
This patch adds host controller API to allow the USB core to allocate or
deallocate bandwidth for an endpoint. Endpoints are added to or dropped
from a copy of the current schedule by calling add_endpoint() or
drop_endpoint(), and then the schedule is atomically evaluated with a
call to check_bandwidth(). This allows all the endpoints for a new
configuration or alternate setting to be added at the same time that the
endpoints from the old configuration or alt setting are dropped.
Endpoints must be added to the schedule before any URBs are submitted to
them. The HCD must be allowed to reject a new configuration or alt
setting before the control transfer is sent to the device requesting the
change. It may reject the change because there is not enough bandwidth,
not enough internal resources (such as memory on an embedded host
controller), or perhaps even for security reasons in a virtualized
environment.
If the call to check_bandwidth() fails, the USB core must call
reset_bandwidth(). This causes the schedule to be reverted back to the
state it was in just after the last successful check_bandwidth() call.
If the call succeeds, the host controller driver (and hardware) will have
changed its internal state to match the new configuration or alternate
setting. The USB core can then issue a control transfer to the device to
change the configuration or alt setting. This allows the core to test new
configurations or alternate settings before unbinding drivers bound to
interfaces in the old configuration.
WIP:
The USB core must add endpoints from all interfaces in a configuration
to the schedule, because a driver may claim that interface at any time.
A slight optimization might be to add the endpoints to the schedule once
a driver claims that interface. FIXME
This patch does not cover changing alternate settings, but it does
handle a configuration change or de-configuration. FIXME
The code for managing the schedule is currently HCD specific. A generic
scheduling algorithm could be added for host controllers without
built-in scheduling support. For now, if a host controller does not
define the check_bandwidth() function, the call to
usb_hcd_check_bandwidth() will always succeed.
Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2009-04-28 09:58:26 +07:00
|
|
|
/* Drop an endpoint from a new schedule */
|
2010-05-18 00:58:12 +07:00
|
|
|
int (*drop_endpoint)(struct usb_hcd *, struct usb_device *,
|
|
|
|
struct usb_host_endpoint *);
|
USB: Support for bandwidth allocation.
Originally, the USB core had no support for allocating bandwidth when a
particular configuration or alternate setting for an interface was
selected. Instead, the device driver's URB submission would fail if
there was not enough bandwidth for a periodic endpoint. Drivers could
work around this, by using the scatter-gather list API to guarantee
bandwidth.
This patch adds host controller API to allow the USB core to allocate or
deallocate bandwidth for an endpoint. Endpoints are added to or dropped
from a copy of the current schedule by calling add_endpoint() or
drop_endpoint(), and then the schedule is atomically evaluated with a
call to check_bandwidth(). This allows all the endpoints for a new
configuration or alternate setting to be added at the same time that the
endpoints from the old configuration or alt setting are dropped.
Endpoints must be added to the schedule before any URBs are submitted to
them. The HCD must be allowed to reject a new configuration or alt
setting before the control transfer is sent to the device requesting the
change. It may reject the change because there is not enough bandwidth,
not enough internal resources (such as memory on an embedded host
controller), or perhaps even for security reasons in a virtualized
environment.
If the call to check_bandwidth() fails, the USB core must call
reset_bandwidth(). This causes the schedule to be reverted back to the
state it was in just after the last successful check_bandwidth() call.
If the call succeeds, the host controller driver (and hardware) will have
changed its internal state to match the new configuration or alternate
setting. The USB core can then issue a control transfer to the device to
change the configuration or alt setting. This allows the core to test new
configurations or alternate settings before unbinding drivers bound to
interfaces in the old configuration.
WIP:
The USB core must add endpoints from all interfaces in a configuration
to the schedule, because a driver may claim that interface at any time.
A slight optimization might be to add the endpoints to the schedule once
a driver claims that interface. FIXME
This patch does not cover changing alternate settings, but it does
handle a configuration change or de-configuration. FIXME
The code for managing the schedule is currently HCD specific. A generic
scheduling algorithm could be added for host controllers without
built-in scheduling support. For now, if a host controller does not
define the check_bandwidth() function, the call to
usb_hcd_check_bandwidth() will always succeed.
Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2009-04-28 09:58:26 +07:00
|
|
|
/* Check that a new hardware configuration, set using
|
|
|
|
* endpoint_enable and endpoint_disable, does not exceed bus
|
|
|
|
* bandwidth. This must be called before any set configuration
|
|
|
|
* or set interface requests are sent to the device.
|
|
|
|
*/
|
|
|
|
int (*check_bandwidth)(struct usb_hcd *, struct usb_device *);
|
|
|
|
/* Reset the device schedule to the last known good schedule,
|
|
|
|
* which was set from a previous successful call to
|
|
|
|
* check_bandwidth(). This reverts any add_endpoint() and
|
|
|
|
* drop_endpoint() calls since that last successful call.
|
|
|
|
* Used for when a check_bandwidth() call fails due to resource
|
|
|
|
* or bandwidth constraints.
|
|
|
|
*/
|
|
|
|
void (*reset_bandwidth)(struct usb_hcd *, struct usb_device *);
|
2009-04-28 09:57:26 +07:00
|
|
|
/* Returns the hardware-chosen device address */
|
|
|
|
int (*address_device)(struct usb_hcd *, struct usb_device *udev);
|
2013-12-06 08:07:27 +07:00
|
|
|
/* prepares the hardware to send commands to the device */
|
|
|
|
int (*enable_device)(struct usb_hcd *, struct usb_device *udev);
|
2009-09-05 00:53:24 +07:00
|
|
|
/* Notifies the HCD after a hub descriptor is fetched.
|
|
|
|
* Will block.
|
|
|
|
*/
|
|
|
|
int (*update_hub_device)(struct usb_hcd *, struct usb_device *hdev,
|
|
|
|
struct usb_tt *tt, gfp_t mem_flags);
|
2009-12-10 06:59:17 +07:00
|
|
|
int (*reset_device)(struct usb_hcd *, struct usb_device *);
|
2010-06-04 14:47:55 +07:00
|
|
|
/* Notifies the HCD after a device is connected and its
|
|
|
|
* address is set
|
|
|
|
*/
|
|
|
|
int (*update_device)(struct usb_hcd *, struct usb_device *);
|
2011-09-24 04:19:52 +07:00
|
|
|
int (*set_usb2_hw_lpm)(struct usb_hcd *, struct usb_device *, int);
|
USB: Add support to enable/disable USB3 link states.
There are various functions within the USB core that will need to
disable USB 3.0 link power states. For example, when a USB device
driver is being bound to an interface, we need to disable USB 3.0 LPM
until we know if the driver will allow hub-initiated LPM transitions.
Another example is when the USB core is switching alternate interface
settings. The USB 3.0 timeout values are dependent on what endpoints
are enabled, so we want to ensure that LPM is disabled until the new alt
setting is fully installed.
Multiple functions need to disable LPM, and those functions can even be
nested. For example, usb_bind_interface() could disable LPM, and then
call into the driver probe function, which may attempt to switch to a
different alt setting. Therefore, we need to keep a count of the number
of functions that require LPM to be disabled at any point in time.
Introduce two new USB core API calls, usb_disable_lpm() and
usb_enable_lpm(). These functions increment and decrement a new
variable in the usb_device, lpm_disable_count. If usb_disable_lpm()
fails, it will call usb_enable_lpm() in order to balance the
lpm_disable_count.
These two new functions must be called with the bandwidth_mutex locked.
If the bandwidth_mutex is not already held by the caller, it should
instead call usb_unlocked_disable_lpm() and usb_enable_lpm(), which take
the bandwidth_mutex before calling usb_disable_lpm() and
usb_enable_lpm(), respectively.
Introduce a new variable (timeout) in the usb3_lpm_params structure to
keep track of the currently enabled U1/U2 timeout values. When
usb_disable_lpm() is called, and the USB device has the U1 or U2
timeouts set to a non-zero value (meaning either device-initiated or
hub-initiated LPM is enabled), attempt to disable LPM, regardless of the
state of the lpm_disable_count. We want to ensure that all callers can
be guaranteed that LPM is disabled if usb_disable_lpm() returns zero.
Otherwise the following scenario could occur:
1. Driver A is being bound to interface 1. usb_probe_interface()
disables LPM. Driver A doesn't care if hub-initiated LPM is enabled, so
even though usb_disable_lpm() fails, the probe of the driver continues,
and the bandwidth mutex is dropped.
2. Meanwhile, Driver B is being bound to interface 2.
usb_probe_interface() grabs the bandwidth mutex and calls
usb_disable_lpm(). That call should attempt to disable LPM, even
though the lpm_disable_count is set to 1 by Driver A.
For usb_enable_lpm(), we attempt to enable LPM only when the
lpm_disable_count is zero. If some step in enabling LPM fails, it will
only have a minimal impact on power consumption, and all USB device
drivers should still work properly. Therefore don't bother to return
any error codes.
Don't enable device-initiated LPM if the device is unconfigured. The
USB device will only accept the U1/U2_ENABLE control transfers in the
configured state. Do enable hub-initiated LPM in that case, since
devices are allowed to accept the LGO_Ux link commands in any state.
Don't enable or disable LPM if the device is marked as not being LPM
capable. This can happen if:
- the USB device doesn't have a SS BOS descriptor,
- the device's parent hub has a zeroed bHeaderDecodeLatency value, or
- the xHCI host doesn't support LPM.
Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Cc: Andiry Xu <andiry.xu@amd.com>
Cc: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
2012-04-25 07:21:50 +07:00
|
|
|
/* USB 3.0 Link Power Management */
|
|
|
|
/* Returns the USB3 hub-encoded value for the U1/U2 timeout. */
|
|
|
|
int (*enable_usb3_lpm_timeout)(struct usb_hcd *,
|
|
|
|
struct usb_device *, enum usb3_link_state state);
|
|
|
|
/* The xHCI host controller can still fail the command to
|
|
|
|
* disable the LPM timeouts, so this can return an error code.
|
|
|
|
*/
|
|
|
|
int (*disable_usb3_lpm_timeout)(struct usb_hcd *,
|
|
|
|
struct usb_device *, enum usb3_link_state state);
|
2013-03-19 15:48:12 +07:00
|
|
|
int (*find_raw_port_number)(struct usb_hcd *, int);
|
2014-10-13 08:53:03 +07:00
|
|
|
/* Call for power on/off the port if necessary */
|
|
|
|
int (*port_power)(struct usb_hcd *hcd, int portnum, bool enable);
|
|
|
|
|
2005-04-17 05:20:36 +07:00
|
|
|
};
|
|
|
|
|
USB: HCD: support giveback of URB in tasklet context
This patch implements the mechanism of giveback of URB in
tasklet context, so that hardware interrupt handling time for
usb host controller can be saved much, and HCD interrupt handling
can be simplified.
Motivations:
1), on some arch(such as ARM), DMA mapping/unmapping is a bit
time-consuming, for example: when accessing usb mass storage
via EHCI on pandaboard, the common length of transfer buffer is 120KB,
the time consumed on DMA unmapping may reach hundreds of microseconds;
even on A15 based box, the time is still about scores of microseconds
2), on some arch, reading DMA coherent memoery is very time-consuming,
the most common example is usb video class driver[1]
3), driver's complete() callback may do much things which is driver
specific, so the time is consumed unnecessarily in hardware irq context.
4), running driver's complete() callback in hardware irq context causes
that host controller driver has to release its lock in interrupt handler,
so reacquiring the lock after return may busy wait a while and increase
interrupt handling time. More seriously, releasing the HCD lock makes
HCD becoming quite complicated to deal with introduced races.
So the patch proposes to run giveback of URB in tasklet context, then
time consumed in HCD irq handling doesn't depend on drivers' complete and
DMA mapping/unmapping any more, also we can simplify HCD since the HCD
lock isn't needed to be released during irq handling.
The patch should be reasonable and doable:
1), for drivers, they don't care if the complete() is called in hard irq
context or softirq context
2), the biggest change is the situation in which usb_submit_urb() is called
in complete() callback, so the introduced tasklet schedule delay might be a
con, but it shouldn't be a big deal:
- control/bulk asynchronous transfer isn't sensitive to schedule
delay
- the patch schedules giveback of periodic URBs using
tasklet_hi_schedule, so the introduced delay should be very
small
- for ISOC transfer, generally, drivers submit several URBs
concurrently to avoid interrupt delay, so it is OK with the
little schedule delay.
- for interrupt transfer, generally, drivers only submit one URB
at the same time, but interrupt transfer is often used in event
report, polling, ... situations, and a little delay should be OK.
Considered that HCDs may optimize on submitting URB in complete(), the
patch may cause the optimization not working, so introduces one flag to mark
if the HCD supports to run giveback URB in tasklet context. When all HCDs
are ready, the flag can be removed.
[1], http://marc.info/?t=136438111600010&r=1&w=2
Cc: Oliver Neukum <oliver@neukum.org>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Ming Lei <ming.lei@canonical.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-07-03 21:53:07 +07:00
|
|
|
static inline int hcd_giveback_urb_in_bh(struct usb_hcd *hcd)
|
|
|
|
{
|
|
|
|
return hcd->driver->flags & HCD_BH;
|
|
|
|
}
|
|
|
|
|
2013-09-04 00:58:43 +07:00
|
|
|
static inline bool hcd_periodic_completion_in_progress(struct usb_hcd *hcd,
|
|
|
|
struct usb_host_endpoint *ep)
|
|
|
|
{
|
|
|
|
return hcd->high_prio_bh.completing_ep == ep;
|
|
|
|
}
|
|
|
|
|
2007-08-08 22:48:02 +07:00
|
|
|
extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb);
|
|
|
|
extern int usb_hcd_check_unlink_urb(struct usb_hcd *hcd, struct urb *urb,
|
|
|
|
int status);
|
|
|
|
extern void usb_hcd_unlink_urb_from_ep(struct usb_hcd *hcd, struct urb *urb);
|
|
|
|
|
2008-01-31 06:21:33 +07:00
|
|
|
extern int usb_hcd_submit_urb(struct urb *urb, gfp_t mem_flags);
|
|
|
|
extern int usb_hcd_unlink_urb(struct urb *urb, int status);
|
2007-08-25 02:42:24 +07:00
|
|
|
extern void usb_hcd_giveback_urb(struct usb_hcd *hcd, struct urb *urb,
|
|
|
|
int status);
|
2011-01-27 10:06:48 +07:00
|
|
|
extern int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
|
|
|
|
gfp_t mem_flags);
|
2011-01-27 10:06:47 +07:00
|
|
|
extern void usb_hcd_unmap_urb_setup_for_dma(struct usb_hcd *, struct urb *);
|
|
|
|
extern void usb_hcd_unmap_urb_for_dma(struct usb_hcd *, struct urb *);
|
2007-09-10 22:33:05 +07:00
|
|
|
extern void usb_hcd_flush_endpoint(struct usb_device *udev,
|
|
|
|
struct usb_host_endpoint *ep);
|
|
|
|
extern void usb_hcd_disable_endpoint(struct usb_device *udev,
|
2006-08-30 22:27:36 +07:00
|
|
|
struct usb_host_endpoint *ep);
|
2009-04-09 00:36:28 +07:00
|
|
|
extern void usb_hcd_reset_endpoint(struct usb_device *udev,
|
|
|
|
struct usb_host_endpoint *ep);
|
2008-10-22 02:28:46 +07:00
|
|
|
extern void usb_hcd_synchronize_unlinks(struct usb_device *udev);
|
USB: Check bandwidth when switching alt settings.
Make the USB core check the bandwidth when switching from one
interface alternate setting to another. Also check the bandwidth
when resetting a configuration (so that alt setting 0 is used). If
this check fails, the device's state is unchanged. If the device
refuses the new alt setting, re-instate the old alt setting in the
host controller hardware.
If a USB device doesn't have an alternate interface setting 0, install
the first alt setting in its descriptors when a new configuration is
requested, or the device is reset.
Add a mutex per root hub to protect bandwidth operations:
adding/reseting/changing configurations, and changing alternate interface
settings. We want to ensure that the xHCI host controller and the USB
device are set up for the same configurations and alternate settings.
There are two (possibly three) steps to do this:
1. The host controller needs to check that bandwidth is available for a
different setting, by issuing and waiting for a configure endpoint
command.
2. Once that returns successfully, a control message is sent to the
device.
3. If that fails, the host controller must be notified through another
configure endpoint command.
The mutex is used to make these three operations seem atomic, to prevent
another driver from using more bandwidth for a different device while
we're in the middle of these operations.
While we're touching the bandwidth code, rename usb_hcd_check_bandwidth()
to usb_hcd_alloc_bandwidth(). This function does more than just check
that the bandwidth change won't exceed the bus bandwidth; it actually
changes the bandwidth configuration in the xHCI host controller.
Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2009-12-04 00:44:36 +07:00
|
|
|
extern int usb_hcd_alloc_bandwidth(struct usb_device *udev,
|
USB: Support for bandwidth allocation.
Originally, the USB core had no support for allocating bandwidth when a
particular configuration or alternate setting for an interface was
selected. Instead, the device driver's URB submission would fail if
there was not enough bandwidth for a periodic endpoint. Drivers could
work around this, by using the scatter-gather list API to guarantee
bandwidth.
This patch adds host controller API to allow the USB core to allocate or
deallocate bandwidth for an endpoint. Endpoints are added to or dropped
from a copy of the current schedule by calling add_endpoint() or
drop_endpoint(), and then the schedule is atomically evaluated with a
call to check_bandwidth(). This allows all the endpoints for a new
configuration or alternate setting to be added at the same time that the
endpoints from the old configuration or alt setting are dropped.
Endpoints must be added to the schedule before any URBs are submitted to
them. The HCD must be allowed to reject a new configuration or alt
setting before the control transfer is sent to the device requesting the
change. It may reject the change because there is not enough bandwidth,
not enough internal resources (such as memory on an embedded host
controller), or perhaps even for security reasons in a virtualized
environment.
If the call to check_bandwidth() fails, the USB core must call
reset_bandwidth(). This causes the schedule to be reverted back to the
state it was in just after the last successful check_bandwidth() call.
If the call succeeds, the host controller driver (and hardware) will have
changed its internal state to match the new configuration or alternate
setting. The USB core can then issue a control transfer to the device to
change the configuration or alt setting. This allows the core to test new
configurations or alternate settings before unbinding drivers bound to
interfaces in the old configuration.
WIP:
The USB core must add endpoints from all interfaces in a configuration
to the schedule, because a driver may claim that interface at any time.
A slight optimization might be to add the endpoints to the schedule once
a driver claims that interface. FIXME
This patch does not cover changing alternate settings, but it does
handle a configuration change or de-configuration. FIXME
The code for managing the schedule is currently HCD specific. A generic
scheduling algorithm could be added for host controllers without
built-in scheduling support. For now, if a host controller does not
define the check_bandwidth() function, the call to
usb_hcd_check_bandwidth() will always succeed.
Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2009-04-28 09:58:26 +07:00
|
|
|
struct usb_host_config *new_config,
|
USB: Check bandwidth when switching alt settings.
Make the USB core check the bandwidth when switching from one
interface alternate setting to another. Also check the bandwidth
when resetting a configuration (so that alt setting 0 is used). If
this check fails, the device's state is unchanged. If the device
refuses the new alt setting, re-instate the old alt setting in the
host controller hardware.
If a USB device doesn't have an alternate interface setting 0, install
the first alt setting in its descriptors when a new configuration is
requested, or the device is reset.
Add a mutex per root hub to protect bandwidth operations:
adding/reseting/changing configurations, and changing alternate interface
settings. We want to ensure that the xHCI host controller and the USB
device are set up for the same configurations and alternate settings.
There are two (possibly three) steps to do this:
1. The host controller needs to check that bandwidth is available for a
different setting, by issuing and waiting for a configure endpoint
command.
2. Once that returns successfully, a control message is sent to the
device.
3. If that fails, the host controller must be notified through another
configure endpoint command.
The mutex is used to make these three operations seem atomic, to prevent
another driver from using more bandwidth for a different device while
we're in the middle of these operations.
While we're touching the bandwidth code, rename usb_hcd_check_bandwidth()
to usb_hcd_alloc_bandwidth(). This function does more than just check
that the bandwidth change won't exceed the bus bandwidth; it actually
changes the bandwidth configuration in the xHCI host controller.
Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2009-12-04 00:44:36 +07:00
|
|
|
struct usb_host_interface *old_alt,
|
|
|
|
struct usb_host_interface *new_alt);
|
2008-01-31 06:21:33 +07:00
|
|
|
extern int usb_hcd_get_frame_number(struct usb_device *udev);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2017-03-13 09:18:41 +07:00
|
|
|
struct usb_hcd *__usb_create_hcd(const struct hc_driver *driver,
|
|
|
|
struct device *sysdev, struct device *dev, const char *bus_name,
|
|
|
|
struct usb_hcd *primary_hcd);
|
2008-01-31 06:21:33 +07:00
|
|
|
extern struct usb_hcd *usb_create_hcd(const struct hc_driver *driver,
|
2008-07-03 02:46:22 +07:00
|
|
|
struct device *dev, const char *bus_name);
|
usb: Make core allocate resources per PCI-device.
Introduce the notion of a PCI device that may be associated with more than
one USB host controller driver (struct usb_hcd). This patch is the start
of the work to separate the xHCI host controller into two roothubs: a USB
3.0 roothub with SuperSpeed-only ports, and a USB 2.0 roothub with
HS/FS/LS ports.
One usb_hcd structure is designated to be the "primary HCD", and a pointer
is added to the usb_hcd structure to keep track of that. A new function
call, usb_hcd_is_primary_hcd() is added to check whether the USB hcd is
marked as the primary HCD (or if it is not part of a roothub pair). To
allow the USB core and xHCI driver to access either roothub in a pair, a
"shared_hcd" pointer is added to the usb_hcd structure.
Add a new function, usb_create_shared_hcd(), that does roothub allocation
for paired roothubs. It will act just like usb_create_hcd() did if the
primary_hcd pointer argument is NULL. If it is passed a non-NULL
primary_hcd pointer, it sets usb_hcd->shared_hcd and usb_hcd->primary_hcd
fields. It will also skip the bandwidth_mutex allocation, and set the
secondary hcd's bandwidth_mutex pointer to the primary HCD's mutex.
IRQs are only allocated once for the primary roothub.
Introduce a new usb_hcd driver flag that indicates the host controller
driver wants to create two roothubs. If the HCD_SHARED flag is set, then
the USB core PCI probe methods will allocate a second roothub, and make
sure that second roothub gets freed during rmmod and in initialization
error paths.
When usb_hc_died() is called with the primary HCD, make sure that any
roothubs that share that host controller are also marked as being dead.
Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
2010-10-29 05:40:26 +07:00
|
|
|
extern struct usb_hcd *usb_create_shared_hcd(const struct hc_driver *driver,
|
|
|
|
struct device *dev, const char *bus_name,
|
|
|
|
struct usb_hcd *shared_hcd);
|
2008-01-31 06:21:33 +07:00
|
|
|
extern struct usb_hcd *usb_get_hcd(struct usb_hcd *hcd);
|
|
|
|
extern void usb_put_hcd(struct usb_hcd *hcd);
|
usb: Make core allocate resources per PCI-device.
Introduce the notion of a PCI device that may be associated with more than
one USB host controller driver (struct usb_hcd). This patch is the start
of the work to separate the xHCI host controller into two roothubs: a USB
3.0 roothub with SuperSpeed-only ports, and a USB 2.0 roothub with
HS/FS/LS ports.
One usb_hcd structure is designated to be the "primary HCD", and a pointer
is added to the usb_hcd structure to keep track of that. A new function
call, usb_hcd_is_primary_hcd() is added to check whether the USB hcd is
marked as the primary HCD (or if it is not part of a roothub pair). To
allow the USB core and xHCI driver to access either roothub in a pair, a
"shared_hcd" pointer is added to the usb_hcd structure.
Add a new function, usb_create_shared_hcd(), that does roothub allocation
for paired roothubs. It will act just like usb_create_hcd() did if the
primary_hcd pointer argument is NULL. If it is passed a non-NULL
primary_hcd pointer, it sets usb_hcd->shared_hcd and usb_hcd->primary_hcd
fields. It will also skip the bandwidth_mutex allocation, and set the
secondary hcd's bandwidth_mutex pointer to the primary HCD's mutex.
IRQs are only allocated once for the primary roothub.
Introduce a new usb_hcd driver flag that indicates the host controller
driver wants to create two roothubs. If the HCD_SHARED flag is set, then
the USB core PCI probe methods will allocate a second roothub, and make
sure that second roothub gets freed during rmmod and in initialization
error paths.
When usb_hc_died() is called with the primary HCD, make sure that any
roothubs that share that host controller are also marked as being dead.
Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
2010-10-29 05:40:26 +07:00
|
|
|
extern int usb_hcd_is_primary_hcd(struct usb_hcd *hcd);
|
2005-04-17 05:20:36 +07:00
|
|
|
extern int usb_add_hcd(struct usb_hcd *hcd,
|
|
|
|
unsigned int irqnum, unsigned long irqflags);
|
|
|
|
extern void usb_remove_hcd(struct usb_hcd *hcd);
|
2013-03-19 15:48:12 +07:00
|
|
|
extern int usb_hcd_find_raw_port_number(struct usb_hcd *hcd, int port1);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
USB: Properly unregister reboot notifier in case of failure in ehci hcd
If some problem occurs during ehci startup, for instance, request_irq fails,
echi hcd driver tries it best to cleanup, but fails to unregister reboot
notifier, which in turn leads to crash on reboot/poweroff.
The following patch resolves this problem by not using reboot notifiers
anymore, but instead making ehci/ohci driver get its own shutdown method. For
PCI, it is done through pci glue, for everything else through platform driver
glue.
One downside: sa1111 does not use platform driver stuff, and does not have its
own shutdown hook, so no 'shutdown' is called for it now. I'm not sure if it
is really necessary on that platform, though.
Signed-off-by: Aleks Gorelov <dared1st@yahoo.com>
Cc: Alan Stern <stern@rowland.harvard.edu>
Cc: David Brownell <david-b@pacbell.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2006-08-09 07:24:08 +07:00
|
|
|
struct platform_device;
|
2008-01-31 06:21:33 +07:00
|
|
|
extern void usb_hcd_platform_shutdown(struct platform_device *dev);
|
USB: Properly unregister reboot notifier in case of failure in ehci hcd
If some problem occurs during ehci startup, for instance, request_irq fails,
echi hcd driver tries it best to cleanup, but fails to unregister reboot
notifier, which in turn leads to crash on reboot/poweroff.
The following patch resolves this problem by not using reboot notifiers
anymore, but instead making ehci/ohci driver get its own shutdown method. For
PCI, it is done through pci glue, for everything else through platform driver
glue.
One downside: sa1111 does not use platform driver stuff, and does not have its
own shutdown hook, so no 'shutdown' is called for it now. I'm not sure if it
is really necessary on that platform, though.
Signed-off-by: Aleks Gorelov <dared1st@yahoo.com>
Cc: Alan Stern <stern@rowland.harvard.edu>
Cc: David Brownell <david-b@pacbell.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2006-08-09 07:24:08 +07:00
|
|
|
|
2017-02-25 18:20:55 +07:00
|
|
|
#ifdef CONFIG_USB_PCI
|
2005-04-17 05:20:36 +07:00
|
|
|
struct pci_dev;
|
|
|
|
struct pci_device_id;
|
2008-01-31 06:21:33 +07:00
|
|
|
extern int usb_hcd_pci_probe(struct pci_dev *dev,
|
2005-04-17 05:20:36 +07:00
|
|
|
const struct pci_device_id *id);
|
2008-01-31 06:21:33 +07:00
|
|
|
extern void usb_hcd_pci_remove(struct pci_dev *dev);
|
|
|
|
extern void usb_hcd_pci_shutdown(struct pci_dev *dev);
|
USB: Properly unregister reboot notifier in case of failure in ehci hcd
If some problem occurs during ehci startup, for instance, request_irq fails,
echi hcd driver tries it best to cleanup, but fails to unregister reboot
notifier, which in turn leads to crash on reboot/poweroff.
The following patch resolves this problem by not using reboot notifiers
anymore, but instead making ehci/ohci driver get its own shutdown method. For
PCI, it is done through pci glue, for everything else through platform driver
glue.
One downside: sa1111 does not use platform driver stuff, and does not have its
own shutdown hook, so no 'shutdown' is called for it now. I'm not sure if it
is really necessary on that platform, though.
Signed-off-by: Aleks Gorelov <dared1st@yahoo.com>
Cc: Alan Stern <stern@rowland.harvard.edu>
Cc: David Brownell <david-b@pacbell.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2006-08-09 07:24:08 +07:00
|
|
|
|
2013-09-16 22:47:28 +07:00
|
|
|
extern int usb_hcd_amd_remote_wakeup_quirk(struct pci_dev *dev);
|
|
|
|
|
2013-08-30 21:46:00 +07:00
|
|
|
#ifdef CONFIG_PM
|
2009-12-15 09:00:08 +07:00
|
|
|
extern const struct dev_pm_ops usb_hcd_pci_pm_ops;
|
2009-04-28 00:33:24 +07:00
|
|
|
#endif
|
2017-02-25 18:20:55 +07:00
|
|
|
#endif /* CONFIG_USB_PCI */
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
/* pci-ish (pdev null is ok) buffer alloc/mapping support */
|
2014-12-05 21:13:54 +07:00
|
|
|
void usb_init_pool_max(void);
|
2008-01-31 06:21:33 +07:00
|
|
|
int hcd_buffer_create(struct usb_hcd *hcd);
|
|
|
|
void hcd_buffer_destroy(struct usb_hcd *hcd);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2008-01-31 06:21:33 +07:00
|
|
|
void *hcd_buffer_alloc(struct usb_bus *bus, size_t size,
|
2005-10-21 14:21:58 +07:00
|
|
|
gfp_t mem_flags, dma_addr_t *dma);
|
2008-01-31 06:21:33 +07:00
|
|
|
void hcd_buffer_free(struct usb_bus *bus, size_t size,
|
2005-04-17 05:20:36 +07:00
|
|
|
void *addr, dma_addr_t dma);
|
|
|
|
|
|
|
|
/* generic bus glue, needed for host controllers that don't use PCI */
|
2008-01-31 06:21:33 +07:00
|
|
|
extern irqreturn_t usb_hcd_irq(int irq, void *__hcd);
|
2005-04-22 02:56:37 +07:00
|
|
|
|
2008-01-31 06:21:33 +07:00
|
|
|
extern void usb_hc_died(struct usb_hcd *hcd);
|
2005-04-22 02:56:37 +07:00
|
|
|
extern void usb_hcd_poll_rh_status(struct usb_hcd *hcd);
|
USB/xHCI: Support device-initiated USB 3.0 resume.
USB 3.0 hubs don't have a port suspend change bit (that bit is now
reserved). Instead, when a host-initiated resume finishes, the hub sets
the port link state change bit.
When a USB 3.0 device initiates remote wakeup, the parent hubs with
their upstream links in U3 will pass the LFPS up the chain. The first
hub that has an upstream link in U0 (which may be the roothub) will
reflect that LFPS back down the path to the device.
However, the parent hubs in the resumed path will not set their link
state change bit. Instead, the device that initiated the resume has to
send an asynchronous "Function Wake" Device Notification up to the host
controller. Therefore, we need a way to notify the USB core of a device
resume without going through the normal hub URB completion method.
First, make the xHCI roothub act like an external USB 3.0 hub and not
pass up the port link state change bit when a device-initiated resume
finishes. Introduce a new xHCI bit field, port_remote_wakeup, so that
we can tell the difference between a port coming out of the U3Exit state
(host-initiated resume) and the RExit state (ending state of
device-initiated resume).
Since the USB core can't tell whether a port on a hub has resumed by
looking at the Hub Status buffer, we need to introduce a bitfield,
wakeup_bits, that indicates which ports have resumed. When the xHCI
driver notices a port finishing a device-initiated resume, we call into
a new USB core function, usb_wakeup_notification(), that will set
the right bit in wakeup_bits, and kick khubd for that hub.
We also call usb_wakeup_notification() when the Function Wake Device
Notification is received by the xHCI driver. This covers the case where
the link between the roothub and the first-tier hub is in U0, and the
hub reflects the resume signaling back to the device without giving any
indication it has done so until the device sends the Function Wake
notification.
Change the code in khubd that handles the remote wakeup to look at the
state the USB core thinks the device is in, and handle the remote wakeup
if the port's wakeup bit is set.
This patch only takes care of the case where the device is attached
directly to the roothub, or the USB 3.0 hub that is attached to the root
hub is the device sending the Function Wake Device Notification (e.g.
because a new USB device was attached). The other cases will be covered
in a second patch.
Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
2011-11-15 09:00:01 +07:00
|
|
|
extern void usb_wakeup_notification(struct usb_device *hdev,
|
|
|
|
unsigned int portnum);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2013-01-26 05:09:42 +07:00
|
|
|
extern void usb_hcd_start_port_resume(struct usb_bus *bus, int portnum);
|
|
|
|
extern void usb_hcd_end_port_resume(struct usb_bus *bus, int portnum);
|
|
|
|
|
2009-04-09 00:36:28 +07:00
|
|
|
/* The D0/D1 toggle bits ... USE WITH CAUTION (they're almost hcd-internal) */
|
|
|
|
#define usb_gettoggle(dev, ep, out) (((dev)->toggle[out] >> (ep)) & 1)
|
|
|
|
#define usb_dotoggle(dev, ep, out) ((dev)->toggle[out] ^= (1 << (ep)))
|
|
|
|
#define usb_settoggle(dev, ep, out, bit) \
|
|
|
|
((dev)->toggle[out] = ((dev)->toggle[out] & ~(1 << (ep))) | \
|
|
|
|
((bit) << (ep)))
|
|
|
|
|
2005-04-17 05:20:36 +07:00
|
|
|
/* -------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
/* Enumeration is only for the hub driver, or HCD virtual root hubs */
|
|
|
|
extern struct usb_device *usb_alloc_dev(struct usb_device *parent,
|
|
|
|
struct usb_bus *, unsigned port);
|
|
|
|
extern int usb_new_device(struct usb_device *dev);
|
|
|
|
extern void usb_disconnect(struct usb_device **);
|
|
|
|
|
|
|
|
extern int usb_get_configuration(struct usb_device *dev);
|
|
|
|
extern void usb_destroy_configuration(struct usb_device *dev);
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* HCD Root Hub support
|
|
|
|
*/
|
|
|
|
|
2010-04-25 04:38:17 +07:00
|
|
|
#include <linux/usb/ch11.h>
|
|
|
|
|
|
|
|
/*
|
|
|
|
* As of USB 2.0, full/low speed devices are segregated into trees.
|
|
|
|
* One type grows from USB 1.1 host controllers (OHCI, UHCI etc).
|
|
|
|
* The other type grows from high speed hubs when they connect to
|
|
|
|
* full/low speed devices using "Transaction Translators" (TTs).
|
|
|
|
*
|
|
|
|
* TTs should only be known to the hub driver, and high speed bus
|
|
|
|
* drivers (only EHCI for now). They affect periodic scheduling and
|
|
|
|
* sometimes control/bulk error recovery.
|
|
|
|
*/
|
|
|
|
|
|
|
|
struct usb_device;
|
|
|
|
|
|
|
|
struct usb_tt {
|
|
|
|
struct usb_device *hub; /* upstream highspeed hub */
|
|
|
|
int multi; /* true means one TT per port */
|
|
|
|
unsigned think_time; /* think time in ns */
|
2013-10-11 22:29:22 +07:00
|
|
|
void *hcpriv; /* HCD private data */
|
2010-04-25 04:38:17 +07:00
|
|
|
|
|
|
|
/* for control/bulk error recovery (CLEAR_TT_BUFFER) */
|
|
|
|
spinlock_t lock;
|
|
|
|
struct list_head clear_list; /* of usb_tt_clear */
|
|
|
|
struct work_struct clear_work;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct usb_tt_clear {
|
|
|
|
struct list_head clear_list;
|
|
|
|
unsigned tt;
|
|
|
|
u16 devinfo;
|
|
|
|
struct usb_hcd *hcd;
|
|
|
|
struct usb_host_endpoint *ep;
|
|
|
|
};
|
|
|
|
|
|
|
|
extern int usb_hub_clear_tt_buffer(struct urb *urb);
|
|
|
|
extern void usb_ep0_reinit(struct usb_device *);
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
/* (shifted) direction/type/recipient from the USB 2.0 spec, table 9.2 */
|
|
|
|
#define DeviceRequest \
|
|
|
|
((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE)<<8)
|
|
|
|
#define DeviceOutRequest \
|
|
|
|
((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_DEVICE)<<8)
|
|
|
|
|
|
|
|
#define InterfaceRequest \
|
|
|
|
((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8)
|
|
|
|
|
|
|
|
#define EndpointRequest \
|
|
|
|
((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8)
|
|
|
|
#define EndpointOutRequest \
|
|
|
|
((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8)
|
|
|
|
|
|
|
|
/* class requests from the USB 2.0 hub spec, table 11-15 */
|
2016-11-18 19:17:26 +07:00
|
|
|
#define HUB_CLASS_REQ(dir, type, request) ((((dir) | (type)) << 8) | (request))
|
2005-04-17 05:20:36 +07:00
|
|
|
/* GetBusState and SetHubDescriptor are optional, omitted */
|
2016-11-18 19:17:26 +07:00
|
|
|
#define ClearHubFeature HUB_CLASS_REQ(USB_DIR_OUT, USB_RT_HUB, USB_REQ_CLEAR_FEATURE)
|
|
|
|
#define ClearPortFeature HUB_CLASS_REQ(USB_DIR_OUT, USB_RT_PORT, USB_REQ_CLEAR_FEATURE)
|
|
|
|
#define GetHubDescriptor HUB_CLASS_REQ(USB_DIR_IN, USB_RT_HUB, USB_REQ_GET_DESCRIPTOR)
|
|
|
|
#define GetHubStatus HUB_CLASS_REQ(USB_DIR_IN, USB_RT_HUB, USB_REQ_GET_STATUS)
|
|
|
|
#define GetPortStatus HUB_CLASS_REQ(USB_DIR_IN, USB_RT_PORT, USB_REQ_GET_STATUS)
|
|
|
|
#define SetHubFeature HUB_CLASS_REQ(USB_DIR_OUT, USB_RT_HUB, USB_REQ_SET_FEATURE)
|
|
|
|
#define SetPortFeature HUB_CLASS_REQ(USB_DIR_OUT, USB_RT_PORT, USB_REQ_SET_FEATURE)
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------*/
|
2010-11-01 23:18:24 +07:00
|
|
|
|
2015-08-08 02:35:51 +07:00
|
|
|
/* class requests from USB 3.1 hub spec, table 10-7 */
|
2016-11-18 19:17:26 +07:00
|
|
|
#define SetHubDepth HUB_CLASS_REQ(USB_DIR_OUT, USB_RT_HUB, HUB_SET_DEPTH)
|
|
|
|
#define GetPortErrorCount HUB_CLASS_REQ(USB_DIR_IN, USB_RT_PORT, HUB_GET_PORT_ERR_COUNT)
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Generic bandwidth allocation constants/support
|
|
|
|
*/
|
|
|
|
#define FRAME_TIME_USECS 1000L
|
2008-01-31 06:21:33 +07:00
|
|
|
#define BitTime(bytecount) (7 * 8 * bytecount / 6) /* with integer truncation */
|
2005-04-17 05:20:36 +07:00
|
|
|
/* Trying not to use worst-case bit-stuffing
|
2008-01-31 06:21:33 +07:00
|
|
|
* of (7/6 * 8 * bytecount) = 9.33 * bytecount */
|
2005-04-17 05:20:36 +07:00
|
|
|
/* bytecount = data payload byte count */
|
|
|
|
|
2013-10-11 22:28:02 +07:00
|
|
|
#define NS_TO_US(ns) DIV_ROUND_UP(ns, 1000L)
|
|
|
|
/* convert nanoseconds to microseconds, rounding up */
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Full/low speed bandwidth allocation constants/support.
|
|
|
|
*/
|
|
|
|
#define BW_HOST_DELAY 1000L /* nanoseconds */
|
|
|
|
#define BW_HUB_LS_SETUP 333L /* nanoseconds */
|
2008-01-31 06:21:33 +07:00
|
|
|
/* 4 full-speed bit times (est.) */
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2008-01-31 06:21:33 +07:00
|
|
|
#define FRAME_TIME_BITS 12000L /* frame = 1 millisecond */
|
2005-04-17 05:20:36 +07:00
|
|
|
#define FRAME_TIME_MAX_BITS_ALLOC (90L * FRAME_TIME_BITS / 100L)
|
|
|
|
#define FRAME_TIME_MAX_USECS_ALLOC (90L * FRAME_TIME_USECS / 100L)
|
|
|
|
|
|
|
|
/*
|
2005-07-30 02:18:28 +07:00
|
|
|
* Ceiling [nano/micro]seconds (typical) for that many bytes at high speed
|
2005-04-17 05:20:36 +07:00
|
|
|
* ISO is a bit less, no ACK ... from USB 2.0 spec, 5.11.3 (and needed
|
|
|
|
* to preallocate bandwidth)
|
|
|
|
*/
|
|
|
|
#define USB2_HOST_DELAY 5 /* nsec, guess */
|
2008-01-31 06:21:33 +07:00
|
|
|
#define HS_NSECS(bytes) (((55 * 8 * 2083) \
|
2005-08-12 09:37:01 +07:00
|
|
|
+ (2083UL * (3 + BitTime(bytes))))/1000 \
|
2005-04-17 05:20:36 +07:00
|
|
|
+ USB2_HOST_DELAY)
|
2008-01-31 06:21:33 +07:00
|
|
|
#define HS_NSECS_ISO(bytes) (((38 * 8 * 2083) \
|
2005-08-12 09:37:01 +07:00
|
|
|
+ (2083UL * (3 + BitTime(bytes))))/1000 \
|
2005-04-17 05:20:36 +07:00
|
|
|
+ USB2_HOST_DELAY)
|
2010-05-18 00:58:12 +07:00
|
|
|
#define HS_USECS(bytes) NS_TO_US(HS_NSECS(bytes))
|
|
|
|
#define HS_USECS_ISO(bytes) NS_TO_US(HS_NSECS_ISO(bytes))
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2008-01-31 06:21:33 +07:00
|
|
|
extern long usb_calc_bus_time(int speed, int is_input,
|
2005-04-17 05:20:36 +07:00
|
|
|
int isoc, int bytecount);
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
extern void usb_set_device_state(struct usb_device *udev,
|
|
|
|
enum usb_device_state new_state);
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
/* exported only within usbcore */
|
|
|
|
|
2016-01-26 02:30:30 +07:00
|
|
|
extern struct idr usb_bus_idr;
|
2016-02-04 05:35:23 +07:00
|
|
|
extern struct mutex usb_bus_idr_lock;
|
2005-04-17 05:20:36 +07:00
|
|
|
extern wait_queue_head_t usb_kill_urb_queue;
|
|
|
|
|
|
|
|
|
|
|
|
#define usb_endpoint_out(ep_dir) (!((ep_dir) & USB_DIR_IN))
|
|
|
|
|
2005-10-14 04:08:02 +07:00
|
|
|
#ifdef CONFIG_PM
|
2008-01-31 06:21:33 +07:00
|
|
|
extern void usb_root_hub_lost_power(struct usb_device *rhdev);
|
2008-11-26 04:39:18 +07:00
|
|
|
extern int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg);
|
|
|
|
extern int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg);
|
2010-01-09 00:57:28 +07:00
|
|
|
extern void usb_hcd_resume_root_hub(struct usb_hcd *hcd);
|
2005-10-14 04:08:02 +07:00
|
|
|
#else
|
2005-10-24 13:04:25 +07:00
|
|
|
static inline void usb_hcd_resume_root_hub(struct usb_hcd *hcd)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2014-11-30 05:47:05 +07:00
|
|
|
#endif /* CONFIG_PM */
|
2010-01-09 00:57:28 +07:00
|
|
|
|
2005-04-17 05:20:36 +07:00
|
|
|
/*-------------------------------------------------------------------------*/
|
|
|
|
|
2008-11-14 11:31:21 +07:00
|
|
|
#if defined(CONFIG_USB_MON) || defined(CONFIG_USB_MON_MODULE)
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
struct usb_mon_operations {
|
|
|
|
void (*urb_submit)(struct usb_bus *bus, struct urb *urb);
|
|
|
|
void (*urb_submit_error)(struct usb_bus *bus, struct urb *urb, int err);
|
2007-08-25 02:41:41 +07:00
|
|
|
void (*urb_complete)(struct usb_bus *bus, struct urb *urb, int status);
|
2005-04-17 05:20:36 +07:00
|
|
|
/* void (*urb_unlink)(struct usb_bus *bus, struct urb *urb); */
|
|
|
|
};
|
|
|
|
|
2015-11-28 22:07:10 +07:00
|
|
|
extern const struct usb_mon_operations *mon_ops;
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
static inline void usbmon_urb_submit(struct usb_bus *bus, struct urb *urb)
|
|
|
|
{
|
|
|
|
if (bus->monitored)
|
|
|
|
(*mon_ops->urb_submit)(bus, urb);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void usbmon_urb_submit_error(struct usb_bus *bus, struct urb *urb,
|
|
|
|
int error)
|
|
|
|
{
|
|
|
|
if (bus->monitored)
|
|
|
|
(*mon_ops->urb_submit_error)(bus, urb, error);
|
|
|
|
}
|
|
|
|
|
2007-08-25 02:41:41 +07:00
|
|
|
static inline void usbmon_urb_complete(struct usb_bus *bus, struct urb *urb,
|
|
|
|
int status)
|
2005-04-17 05:20:36 +07:00
|
|
|
{
|
|
|
|
if (bus->monitored)
|
2007-08-25 02:41:41 +07:00
|
|
|
(*mon_ops->urb_complete)(bus, urb, status);
|
2005-04-17 05:20:36 +07:00
|
|
|
}
|
|
|
|
|
2015-11-28 22:07:10 +07:00
|
|
|
int usb_mon_register(const struct usb_mon_operations *ops);
|
2005-04-17 05:20:36 +07:00
|
|
|
void usb_mon_deregister(void);
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
static inline void usbmon_urb_submit(struct usb_bus *bus, struct urb *urb) {}
|
|
|
|
static inline void usbmon_urb_submit_error(struct usb_bus *bus, struct urb *urb,
|
|
|
|
int error) {}
|
2007-08-25 02:41:41 +07:00
|
|
|
static inline void usbmon_urb_complete(struct usb_bus *bus, struct urb *urb,
|
|
|
|
int status) {}
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2008-11-14 11:31:21 +07:00
|
|
|
#endif /* CONFIG_USB_MON || CONFIG_USB_MON_MODULE */
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
/* random stuff */
|
|
|
|
|
2008-01-31 06:21:33 +07:00
|
|
|
#define RUN_CONTEXT (in_irq() ? "in_irq" \
|
|
|
|
: (in_interrupt() ? "in_interrupt" : "can sleep"))
|
2005-04-17 05:20:36 +07:00
|
|
|
|
|
|
|
|
2007-10-11 03:27:07 +07:00
|
|
|
/* This rwsem is for use only by the hub driver and ehci-hcd.
|
|
|
|
* Nobody else should touch it.
|
|
|
|
*/
|
|
|
|
extern struct rw_semaphore ehci_cf_port_reset_rwsem;
|
2005-04-17 05:20:36 +07:00
|
|
|
|
2008-10-02 22:48:13 +07:00
|
|
|
/* Keep track of which host controller drivers are loaded */
|
|
|
|
#define USB_UHCI_LOADED 0
|
|
|
|
#define USB_OHCI_LOADED 1
|
|
|
|
#define USB_EHCI_LOADED 2
|
|
|
|
extern unsigned long usb_hcds_loaded;
|
|
|
|
|
2007-10-11 03:27:07 +07:00
|
|
|
#endif /* __KERNEL__ */
|
2008-10-30 04:25:50 +07:00
|
|
|
|
|
|
|
#endif /* __USB_CORE_HCD_H */
|