git://git.onelab.eu
/
linux-2.6.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git]
/
drivers
/
usb
/
host
/
ehci-sched.c
diff --git
a/drivers/usb/host/ehci-sched.c
b/drivers/usb/host/ehci-sched.c
index
2fa1ffe
..
5871944
100644
(file)
--- a/
drivers/usb/host/ehci-sched.c
+++ b/
drivers/usb/host/ehci-sched.c
@@
-301,7
+301,7
@@
static int qh_link_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh)
dev_dbg (&qh->dev->dev,
"link qh%d-%04x/%p start %d [%d/%d us]\n",
dev_dbg (&qh->dev->dev,
"link qh%d-%04x/%p start %d [%d/%d us]\n",
- period, le32_to_cpup (&qh->hw_info2) &
0xffff
,
+ period, le32_to_cpup (&qh->hw_info2) &
(QH_CMASK | QH_SMASK)
,
qh, qh->start, qh->usecs, qh->c_usecs);
/* high bandwidth, or otherwise every microframe */
qh, qh->start, qh->usecs, qh->c_usecs);
/* high bandwidth, or otherwise every microframe */
@@
-385,7
+385,8
@@
static void qh_unlink_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh)
dev_dbg (&qh->dev->dev,
"unlink qh%d-%04x/%p start %d [%d/%d us]\n",
dev_dbg (&qh->dev->dev,
"unlink qh%d-%04x/%p start %d [%d/%d us]\n",
- qh->period, le32_to_cpup (&qh->hw_info2) & 0xffff,
+ qh->period,
+ le32_to_cpup (&qh->hw_info2) & (QH_CMASK | QH_SMASK),
qh, qh->start, qh->usecs, qh->c_usecs);
/* qh->qh_next still "live" to HC */
qh, qh->start, qh->usecs, qh->c_usecs);
/* qh->qh_next still "live" to HC */
@@
-411,7
+412,7
@@
static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
* active high speed queues may need bigger delays...
*/
if (list_empty (&qh->qtd_list)
* active high speed queues may need bigger delays...
*/
if (list_empty (&qh->qtd_list)
- || (__constant_cpu_to_le32 (
0x0ff << 8
)
+ || (__constant_cpu_to_le32 (
QH_CMASK
)
& qh->hw_info2) != 0)
wait = 2;
else
& qh->hw_info2) != 0)
wait = 2;
else
@@
-533,7
+534,7
@@
static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
/* reuse the previous schedule slots, if we can */
if (frame < qh->period) {
/* reuse the previous schedule slots, if we can */
if (frame < qh->period) {
- uframe = ffs (le32_to_cpup (&qh->hw_info2) &
0x00ff
);
+ uframe = ffs (le32_to_cpup (&qh->hw_info2) &
QH_SMASK
);
status = check_intr_schedule (ehci, frame, --uframe,
qh, &c_mask);
} else {
status = check_intr_schedule (ehci, frame, --uframe,
qh, &c_mask);
} else {
@@
-569,10
+570,10
@@
static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
qh->start = frame;
/* reset S-frame and (maybe) C-frame masks */
qh->start = frame;
/* reset S-frame and (maybe) C-frame masks */
- qh->hw_info2 &= __constant_cpu_to_le32
(~0xffff
);
+ qh->hw_info2 &= __constant_cpu_to_le32
(~(QH_CMASK | QH_SMASK)
);
qh->hw_info2 |= qh->period
? cpu_to_le32 (1 << uframe)
qh->hw_info2 |= qh->period
? cpu_to_le32 (1 << uframe)
- : __constant_cpu_to_le32 (
0xff
);
+ : __constant_cpu_to_le32 (
QH_SMASK
);
qh->hw_info2 |= c_mask;
} else
ehci_dbg (ehci, "reused qh %p schedule\n", qh);
qh->hw_info2 |= c_mask;
} else
ehci_dbg (ehci, "reused qh %p schedule\n", qh);
@@
-588,7
+589,7
@@
static int intr_submit (
struct usb_host_endpoint *ep,
struct urb *urb,
struct list_head *qtd_list,
struct usb_host_endpoint *ep,
struct urb *urb,
struct list_head *qtd_list,
-
int
mem_flags
+
gfp_t
mem_flags
) {
unsigned epnum;
unsigned long flags;
) {
unsigned epnum;
unsigned long flags;
@@
-601,6
+602,12
@@
static int intr_submit (
spin_lock_irqsave (&ehci->lock, flags);
spin_lock_irqsave (&ehci->lock, flags);
+ if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE,
+ &ehci_to_hcd(ehci)->flags))) {
+ status = -ESHUTDOWN;
+ goto done;
+ }
+
/* get qh and force any scheduling errors */
INIT_LIST_HEAD (&empty);
qh = qh_append_tds (ehci, urb, &empty, epnum, &ep->hcpriv);
/* get qh and force any scheduling errors */
INIT_LIST_HEAD (&empty);
qh = qh_append_tds (ehci, urb, &empty, epnum, &ep->hcpriv);
@@
-633,13
+640,12
@@
done:
/* ehci_iso_stream ops work with both ITD and SITD */
static struct ehci_iso_stream *
/* ehci_iso_stream ops work with both ITD and SITD */
static struct ehci_iso_stream *
-iso_stream_alloc (
in
t mem_flags)
+iso_stream_alloc (
gfp_
t mem_flags)
{
struct ehci_iso_stream *stream;
{
struct ehci_iso_stream *stream;
- stream = k
m
alloc(sizeof *stream, mem_flags);
+ stream = k
z
alloc(sizeof *stream, mem_flags);
if (likely (stream != NULL)) {
if (likely (stream != NULL)) {
- memset (stream, 0, sizeof(*stream));
INIT_LIST_HEAD(&stream->td_list);
INIT_LIST_HEAD(&stream->free_list);
stream->next_uframe = -1;
INIT_LIST_HEAD(&stream->td_list);
INIT_LIST_HEAD(&stream->free_list);
stream->next_uframe = -1;
@@
-700,6
+706,8
@@
iso_stream_init (
} else {
u32 addr;
} else {
u32 addr;
+ int think_time;
+ int hs_transfers;
addr = dev->ttport << 24;
if (!ehci_is_TDI(ehci)
addr = dev->ttport << 24;
if (!ehci_is_TDI(ehci)
@@
-709,6
+717,10
@@
iso_stream_init (
addr |= epnum << 8;
addr |= dev->devnum;
stream->usecs = HS_USECS_ISO (maxp);
addr |= epnum << 8;
addr |= dev->devnum;
stream->usecs = HS_USECS_ISO (maxp);
+ think_time = dev->tt ? dev->tt->think_time : 0;
+ stream->tt_usecs = NS_TO_US (think_time + usb_calc_bus_time (
+ dev->speed, is_input, 1, maxp));
+ hs_transfers = max (1u, (maxp + 187) / 188);
if (is_input) {
u32 tmp;
if (is_input) {
u32 tmp;
@@
-717,12
+729,11
@@
iso_stream_init (
stream->usecs = HS_USECS_ISO (1);
stream->raw_mask = 1;
stream->usecs = HS_USECS_ISO (1);
stream->raw_mask = 1;
- /* pessimistic c-mask */
- tmp = usb_calc_bus_time (USB_SPEED_FULL, 1, 0, maxp)
- / (125 * 1000);
- stream->raw_mask |= 3 << (tmp + 9);
+ /* c-mask as specified in USB 2.0 11.18.4 3.c */
+ tmp = (1 << (hs_transfers + 2)) - 1;
+ stream->raw_mask |= tmp << (8 + 2);
} else
} else
- stream->raw_mask = smask_out [
maxp / 188
];
+ stream->raw_mask = smask_out [
hs_transfers - 1
];
bandwidth = stream->usecs + stream->c_usecs;
bandwidth /= 1 << (interval + 2);
bandwidth = stream->usecs + stream->c_usecs;
bandwidth /= 1 << (interval + 2);
@@
-847,15
+858,14
@@
iso_stream_find (struct ehci_hcd *ehci, struct urb *urb)
/* ehci_iso_sched ops can be ITD-only or SITD-only */
static struct ehci_iso_sched *
/* ehci_iso_sched ops can be ITD-only or SITD-only */
static struct ehci_iso_sched *
-iso_sched_alloc (unsigned packets,
in
t mem_flags)
+iso_sched_alloc (unsigned packets,
gfp_
t mem_flags)
{
struct ehci_iso_sched *iso_sched;
int size = sizeof *iso_sched;
size += packets * sizeof (struct ehci_iso_packet);
{
struct ehci_iso_sched *iso_sched;
int size = sizeof *iso_sched;
size += packets * sizeof (struct ehci_iso_packet);
- iso_sched = k
malloc
(size, mem_flags);
+ iso_sched = k
zalloc
(size, mem_flags);
if (likely (iso_sched != NULL)) {
if (likely (iso_sched != NULL)) {
- memset(iso_sched, 0, size);
INIT_LIST_HEAD (&iso_sched->td_list);
}
return iso_sched;
INIT_LIST_HEAD (&iso_sched->td_list);
}
return iso_sched;
@@
-894,7
+904,7
@@
itd_sched_init (
trans |= length << 16;
uframe->transaction = cpu_to_le32 (trans);
trans |= length << 16;
uframe->transaction = cpu_to_le32 (trans);
- /* might need to cross a buffer page within a
td
*/
+ /* might need to cross a buffer page within a
uframe
*/
uframe->bufp = (buf & ~(u64)0x0fff);
buf += length;
if (unlikely ((uframe->bufp != (buf & ~(u64)0x0fff))))
uframe->bufp = (buf & ~(u64)0x0fff);
buf += length;
if (unlikely ((uframe->bufp != (buf & ~(u64)0x0fff))))
@@
-920,7
+930,7
@@
itd_urb_transaction (
struct ehci_iso_stream *stream,
struct ehci_hcd *ehci,
struct urb *urb,
struct ehci_iso_stream *stream,
struct ehci_hcd *ehci,
struct urb *urb,
-
int
mem_flags
+
gfp_t
mem_flags
)
{
struct ehci_itd *itd;
)
{
struct ehci_itd *itd;
@@
-1053,6
+1063,7
@@
sitd_slot_ok (
/* for IN, check CSPLIT */
if (stream->c_usecs) {
/* for IN, check CSPLIT */
if (stream->c_usecs) {
+ uf = uframe & 7;
max_used = 100 - stream->c_usecs;
do {
tmp = 1 << uf;
max_used = 100 - stream->c_usecs;
do {
tmp = 1 << uf;
@@
-1194,6
+1205,7
@@
itd_init (struct ehci_iso_stream *stream, struct ehci_itd *itd)
{
int i;
{
int i;
+ /* it's been recently zeroed */
itd->hw_next = EHCI_LIST_END;
itd->hw_bufp [0] = stream->buf0;
itd->hw_bufp [1] = stream->buf1;
itd->hw_next = EHCI_LIST_END;
itd->hw_bufp [0] = stream->buf0;
itd->hw_bufp [1] = stream->buf1;
@@
-1210,8
+1222,7
@@
itd_patch (
struct ehci_itd *itd,
struct ehci_iso_sched *iso_sched,
unsigned index,
struct ehci_itd *itd,
struct ehci_iso_sched *iso_sched,
unsigned index,
- u16 uframe,
- int first
+ u16 uframe
)
{
struct ehci_iso_packet *uf = &iso_sched->packet [index];
)
{
struct ehci_iso_packet *uf = &iso_sched->packet [index];
@@
-1228,7
+1239,7
@@
itd_patch (
itd->hw_bufp_hi [pg] |= cpu_to_le32 ((u32)(uf->bufp >> 32));
/* iso_frame_desc[].offset must be strictly increasing */
itd->hw_bufp_hi [pg] |= cpu_to_le32 ((u32)(uf->bufp >> 32));
/* iso_frame_desc[].offset must be strictly increasing */
- if (unlikely (
!first &&
uf->cross)) {
+ if (unlikely (uf->cross)) {
u64 bufp = uf->bufp + 4096;
itd->pg = ++pg;
itd->hw_bufp [pg] |= cpu_to_le32 (bufp & ~(u32)0);
u64 bufp = uf->bufp + 4096;
itd->pg = ++pg;
itd->hw_bufp [pg] |= cpu_to_le32 (bufp & ~(u32)0);
@@
-1257,7
+1268,7
@@
itd_link_urb (
struct ehci_iso_stream *stream
)
{
struct ehci_iso_stream *stream
)
{
- int packet
, first = 1
;
+ int packet;
unsigned next_uframe, uframe, frame;
struct ehci_iso_sched *iso_sched = urb->hcpriv;
struct ehci_itd *itd;
unsigned next_uframe, uframe, frame;
struct ehci_iso_sched *iso_sched = urb->hcpriv;
struct ehci_itd *itd;
@@
-1290,7
+1301,6
@@
itd_link_urb (
list_move_tail (&itd->itd_list, &stream->td_list);
itd->stream = iso_stream_get (stream);
itd->urb = usb_get_urb (urb);
list_move_tail (&itd->itd_list, &stream->td_list);
itd->stream = iso_stream_get (stream);
itd->urb = usb_get_urb (urb);
- first = 1;
itd_init (stream, itd);
}
itd_init (stream, itd);
}
@@
-1298,8
+1308,7
@@
itd_link_urb (
frame = next_uframe >> 3;
itd->usecs [uframe] = stream->usecs;
frame = next_uframe >> 3;
itd->usecs [uframe] = stream->usecs;
- itd_patch (itd, iso_sched, packet, uframe, first);
- first = 0;
+ itd_patch (itd, iso_sched, packet, uframe);
next_uframe += stream->interval;
stream->depth += stream->interval;
next_uframe += stream->interval;
stream->depth += stream->interval;
@@
-1389,7
+1398,7
@@
itd_complete (
*/
/* give urb back to the driver ... can be out-of-order */
*/
/* give urb back to the driver ... can be out-of-order */
- dev = u
sb_get_dev (urb->dev)
;
+ dev = u
rb->dev
;
ehci_urb_done (ehci, urb, regs);
urb = NULL;
ehci_urb_done (ehci, urb, regs);
urb = NULL;
@@
-1408,14
+1417,14
@@
itd_complete (
(stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out");
}
iso_stream_put (ehci, stream);
(stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out");
}
iso_stream_put (ehci, stream);
- usb_put_dev (dev);
return 1;
}
/*-------------------------------------------------------------------------*/
return 1;
}
/*-------------------------------------------------------------------------*/
-static int itd_submit (struct ehci_hcd *ehci, struct urb *urb, int mem_flags)
+static int itd_submit (struct ehci_hcd *ehci, struct urb *urb,
+ gfp_t mem_flags)
{
int status = -EINVAL;
unsigned long flags;
{
int status = -EINVAL;
unsigned long flags;
@@
-1453,7
+1462,11
@@
static int itd_submit (struct ehci_hcd *ehci, struct urb *urb, int mem_flags)
/* schedule ... need to lock */
spin_lock_irqsave (&ehci->lock, flags);
/* schedule ... need to lock */
spin_lock_irqsave (&ehci->lock, flags);
- status = iso_stream_schedule (ehci, urb, stream);
+ if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE,
+ &ehci_to_hcd(ehci)->flags)))
+ status = -ESHUTDOWN;
+ else
+ status = iso_stream_schedule (ehci, urb, stream);
if (likely (status == 0))
itd_link_urb (ehci, urb, ehci->periodic_size << 3, stream);
spin_unlock_irqrestore (&ehci->lock, flags);
if (likely (status == 0))
itd_link_urb (ehci, urb, ehci->periodic_size << 3, stream);
spin_unlock_irqrestore (&ehci->lock, flags);
@@
-1526,7
+1539,7
@@
sitd_urb_transaction (
struct ehci_iso_stream *stream,
struct ehci_hcd *ehci,
struct urb *urb,
struct ehci_iso_stream *stream,
struct ehci_hcd *ehci,
struct urb *urb,
-
int
mem_flags
+
gfp_t
mem_flags
)
{
struct ehci_sitd *sitd;
)
{
struct ehci_sitd *sitd;
@@
-1750,7
+1763,7
@@
sitd_complete (
*/
/* give urb back to the driver */
*/
/* give urb back to the driver */
- dev = u
sb_get_dev (urb->dev)
;
+ dev = u
rb->dev
;
ehci_urb_done (ehci, urb, regs);
urb = NULL;
ehci_urb_done (ehci, urb, regs);
urb = NULL;
@@
-1769,13
+1782,13
@@
sitd_complete (
(stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out");
}
iso_stream_put (ehci, stream);
(stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out");
}
iso_stream_put (ehci, stream);
- usb_put_dev (dev);
return 1;
}
return 1;
}
-static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb, int mem_flags)
+static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb,
+ gfp_t mem_flags)
{
int status = -EINVAL;
unsigned long flags;
{
int status = -EINVAL;
unsigned long flags;
@@
-1811,7
+1824,11
@@
static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb, int mem_flags)
/* schedule ... need to lock */
spin_lock_irqsave (&ehci->lock, flags);
/* schedule ... need to lock */
spin_lock_irqsave (&ehci->lock, flags);
- status = iso_stream_schedule (ehci, urb, stream);
+ if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE,
+ &ehci_to_hcd(ehci)->flags)))
+ status = -ESHUTDOWN;
+ else
+ status = iso_stream_schedule (ehci, urb, stream);
if (status == 0)
sitd_link_urb (ehci, urb, ehci->periodic_size << 3, stream);
spin_unlock_irqrestore (&ehci->lock, flags);
if (status == 0)
sitd_link_urb (ehci, urb, ehci->periodic_size << 3, stream);
spin_unlock_irqrestore (&ehci->lock, flags);
@@
-1825,7
+1842,7
@@
done:
#else
static inline int
#else
static inline int
-sitd_submit (struct ehci_hcd *ehci, struct urb *urb,
in
t mem_flags)
+sitd_submit (struct ehci_hcd *ehci, struct urb *urb,
gfp_
t mem_flags)
{
ehci_dbg (ehci, "split iso support is disabled\n");
return -ENOSYS;
{
ehci_dbg (ehci, "split iso support is disabled\n");
return -ENOSYS;