Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
2c9fbaf4
Commit
2c9fbaf4
authored
Oct 17, 2002
by
Greg Kroah-Hartman
Browse files
Options
Browse Files
Download
Plain Diff
Merge
bk://ldm.bkbits.net/linux-2.5-core
into kroah.com:/home/greg/linux/BK/gregkh-2.5
parents
a0424fb7
06a15d7e
Changes
11
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
512 additions
and
486 deletions
+512
-486
drivers/usb/core/devio.c
drivers/usb/core/devio.c
+1
-1
drivers/usb/core/message.c
drivers/usb/core/message.c
+1
-1
drivers/usb/core/usb.c
drivers/usb/core/usb.c
+3
-1
drivers/usb/host/uhci-debug.c
drivers/usb/host/uhci-debug.c
+144
-102
drivers/usb/host/uhci-hcd.c
drivers/usb/host/uhci-hcd.c
+258
-277
drivers/usb/host/uhci-hcd.h
drivers/usb/host/uhci-hcd.h
+59
-85
drivers/usb/input/Config.help
drivers/usb/input/Config.help
+4
-2
drivers/usb/input/Config.in
drivers/usb/input/Config.in
+5
-2
drivers/usb/misc/usbtest.c
drivers/usb/misc/usbtest.c
+18
-5
drivers/usb/net/pegasus.h
drivers/usb/net/pegasus.h
+3
-0
drivers/usb/storage/transport.c
drivers/usb/storage/transport.c
+16
-10
No files found.
drivers/usb/core/devio.c
View file @
2c9fbaf4
...
@@ -1077,7 +1077,7 @@ static int proc_ioctl (struct dev_state *ps, void *arg)
...
@@ -1077,7 +1077,7 @@ static int proc_ioctl (struct dev_state *ps, void *arg)
driver
->
name
,
ps
->
dev
->
devnum
,
ctrl
.
ifno
);
driver
->
name
,
ps
->
dev
->
devnum
,
ctrl
.
ifno
);
usb_device_remove
(
&
ifp
->
dev
);
usb_device_remove
(
&
ifp
->
dev
);
}
else
}
else
retval
=
-
E
INVAL
;
retval
=
-
E
NODATA
;
break
;
break
;
/* let kernel drivers try to (re)bind to the interface */
/* let kernel drivers try to (re)bind to the interface */
...
...
drivers/usb/core/message.c
View file @
2c9fbaf4
...
@@ -847,7 +847,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
...
@@ -847,7 +847,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
ep
&=
USB_ENDPOINT_NUMBER_MASK
;
ep
&=
USB_ENDPOINT_NUMBER_MASK
;
usb_settoggle
(
dev
,
ep
,
out
,
0
);
usb_settoggle
(
dev
,
ep
,
out
,
0
);
(
out
?
dev
->
epmaxpacketout
:
dev
->
epmaxpacketin
)
[
ep
]
(
out
?
dev
->
epmaxpacketout
:
dev
->
epmaxpacketin
)
[
ep
]
=
iface_as
->
endpoint
[
ep
].
wMaxPacketSize
;
=
iface_as
->
endpoint
[
i
].
wMaxPacketSize
;
}
}
return
0
;
return
0
;
...
...
drivers/usb/core/usb.c
View file @
2c9fbaf4
...
@@ -790,6 +790,7 @@ void usb_disconnect(struct usb_device **pdev)
...
@@ -790,6 +790,7 @@ void usb_disconnect(struct usb_device **pdev)
usb_disconnect
(
child
);
usb_disconnect
(
child
);
}
}
dbg
(
"unregistering interfaces on device %d"
,
dev
->
devnum
);
if
(
dev
->
actconfig
)
{
if
(
dev
->
actconfig
)
{
for
(
i
=
0
;
i
<
dev
->
actconfig
->
bNumInterfaces
;
i
++
)
{
for
(
i
=
0
;
i
<
dev
->
actconfig
->
bNumInterfaces
;
i
++
)
{
struct
usb_interface
*
interface
=
&
dev
->
actconfig
->
interface
[
i
];
struct
usb_interface
*
interface
=
&
dev
->
actconfig
->
interface
[
i
];
...
@@ -799,12 +800,13 @@ void usb_disconnect(struct usb_device **pdev)
...
@@ -799,12 +800,13 @@ void usb_disconnect(struct usb_device **pdev)
}
}
}
}
dbg
(
"unregistering the device %d"
,
dev
->
devnum
);
/* Free the device number and remove the /proc/bus/usb entry */
/* Free the device number and remove the /proc/bus/usb entry */
if
(
dev
->
devnum
>
0
)
{
if
(
dev
->
devnum
>
0
)
{
clear_bit
(
dev
->
devnum
,
dev
->
bus
->
devmap
.
devicemap
);
clear_bit
(
dev
->
devnum
,
dev
->
bus
->
devmap
.
devicemap
);
usbfs_remove_device
(
dev
);
usbfs_remove_device
(
dev
);
device_unregister
(
&
dev
->
dev
);
}
}
device_unregister
(
&
dev
->
dev
);
/* Decrement the reference count, it'll auto free everything when */
/* Decrement the reference count, it'll auto free everything when */
/* it hits 0 which could very well be now */
/* it hits 0 which could very well be now */
...
...
drivers/usb/host/uhci-debug.c
View file @
2c9fbaf4
...
@@ -34,17 +34,6 @@ static void inline lprintk(char *buf)
...
@@ -34,17 +34,6 @@ static void inline lprintk(char *buf)
}
}
}
}
static
int
inline
uhci_is_skeleton_td
(
struct
uhci_hcd
*
uhci
,
struct
uhci_td
*
td
)
{
int
i
;
for
(
i
=
0
;
i
<
UHCI_NUM_SKELTD
;
i
++
)
if
(
td
==
uhci
->
skeltd
[
i
])
return
1
;
return
0
;
}
static
int
inline
uhci_is_skeleton_qh
(
struct
uhci_hcd
*
uhci
,
struct
uhci_qh
*
qh
)
static
int
inline
uhci_is_skeleton_qh
(
struct
uhci_hcd
*
uhci
,
struct
uhci_qh
*
qh
)
{
{
int
i
;
int
i
;
...
@@ -285,13 +274,14 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space)
...
@@ -285,13 +274,14 @@ static int uhci_show_qh(struct uhci_qh *qh, char *buf, int len, int space)
return
out
-
buf
;
return
out
-
buf
;
}
}
static
const
char
*
td_names
[]
=
{
"skel_int1_td"
,
"skel_int2_td"
,
static
const
char
*
qh_names
[]
=
{
"skel_int4_td"
,
"skel_int8_td"
,
"skel_int128_qh"
,
"skel_int64_qh"
,
"skel_int16_td"
,
"skel_int32_td"
,
"skel_int32_qh"
,
"skel_int16_qh"
,
"skel_int64_td"
,
"skel_int128_td"
,
"skel_int8_qh"
,
"skel_int4_qh"
,
"skel_int256_td"
,
"skel_term_td"
};
"skel_int2_qh"
,
"skel_int1_qh"
,
static
const
char
*
qh_names
[]
=
{
"skel_ls_control_qh"
,
"skel_hs_control_qh"
,
"skel_ls_control_qh"
,
"skel_hs_control_qh"
,
"skel_bulk_qh"
,
"skel_term_qh"
};
"skel_bulk_qh"
,
"skel_term_qh"
};
#define show_frame_num() \
#define show_frame_num() \
if (!shown) { \
if (!shown) { \
...
@@ -299,26 +289,141 @@ static const char *qh_names[] = { "skel_ls_control_qh", "skel_hs_control_qh",
...
@@ -299,26 +289,141 @@ static const char *qh_names[] = { "skel_ls_control_qh", "skel_hs_control_qh",
out += sprintf(out, "- Frame %d\n", i); \
out += sprintf(out, "- Frame %d\n", i); \
}
}
#define show_td_name() \
if (!shown) { \
shown = 1; \
out += sprintf(out, "- %s\n", td_names[i]); \
}
#define show_qh_name() \
#define show_qh_name() \
if (!shown) { \
if (!shown) { \
shown = 1; \
shown = 1; \
out += sprintf(out, "- %s\n", qh_names[i]); \
out += sprintf(out, "- %s\n", qh_names[i]); \
}
}
static
int
uhci_show_urbp
(
struct
uhci_hcd
*
uhci
,
struct
urb_priv
*
urbp
,
char
*
buf
,
int
len
)
{
struct
list_head
*
tmp
;
char
*
out
=
buf
;
int
count
=
0
;
if
(
len
<
200
)
return
0
;
out
+=
sprintf
(
out
,
"urb_priv [%p] "
,
urbp
);
out
+=
sprintf
(
out
,
"urb [%p] "
,
urbp
->
urb
);
out
+=
sprintf
(
out
,
"qh [%p] "
,
urbp
->
qh
);
out
+=
sprintf
(
out
,
"Dev=%d "
,
usb_pipedevice
(
urbp
->
urb
->
pipe
));
out
+=
sprintf
(
out
,
"EP=%x(%s) "
,
usb_pipeendpoint
(
urbp
->
urb
->
pipe
),
(
usb_pipein
(
urbp
->
urb
->
pipe
)
?
"IN"
:
"OUT"
));
switch
(
usb_pipetype
(
urbp
->
urb
->
pipe
))
{
case
PIPE_ISOCHRONOUS
:
out
+=
sprintf
(
out
,
"ISO "
);
break
;
case
PIPE_INTERRUPT
:
out
+=
sprintf
(
out
,
"INT "
);
break
;
case
PIPE_BULK
:
out
+=
sprintf
(
out
,
"BLK "
);
break
;
case
PIPE_CONTROL
:
out
+=
sprintf
(
out
,
"CTL "
);
break
;
}
out
+=
sprintf
(
out
,
"%s"
,
(
urbp
->
fsbr
?
"FSBR "
:
""
));
out
+=
sprintf
(
out
,
"%s"
,
(
urbp
->
fsbr_timeout
?
"FSBR_TO "
:
""
));
if
(
urbp
->
status
!=
-
EINPROGRESS
)
out
+=
sprintf
(
out
,
"Status=%d "
,
urbp
->
status
);
//out += sprintf(out, "Inserttime=%lx ",urbp->inserttime);
//out += sprintf(out, "FSBRtime=%lx ",urbp->fsbrtime);
spin_lock
(
&
urbp
->
urb
->
lock
);
count
=
0
;
list_for_each
(
tmp
,
&
urbp
->
td_list
)
count
++
;
spin_unlock
(
&
urbp
->
urb
->
lock
);
out
+=
sprintf
(
out
,
"TDs=%d "
,
count
);
if
(
urbp
->
queued
)
out
+=
sprintf
(
out
,
"queued
\n
"
);
else
{
spin_lock
(
&
uhci
->
frame_list_lock
);
count
=
0
;
list_for_each
(
tmp
,
&
urbp
->
queue_list
)
count
++
;
spin_unlock
(
&
uhci
->
frame_list_lock
);
out
+=
sprintf
(
out
,
"queued URBs=%d
\n
"
,
count
);
}
return
out
-
buf
;
}
static
int
uhci_show_lists
(
struct
uhci_hcd
*
uhci
,
char
*
buf
,
int
len
)
{
char
*
out
=
buf
;
unsigned
long
flags
;
struct
list_head
*
head
,
*
tmp
;
int
count
;
out
+=
sprintf
(
out
,
"Main list URBs:"
);
spin_lock_irqsave
(
&
uhci
->
urb_list_lock
,
flags
);
if
(
list_empty
(
&
uhci
->
urb_list
))
out
+=
sprintf
(
out
,
" Empty
\n
"
);
else
{
out
+=
sprintf
(
out
,
"
\n
"
);
count
=
0
;
head
=
&
uhci
->
urb_list
;
tmp
=
head
->
next
;
while
(
tmp
!=
head
)
{
struct
urb_priv
*
urbp
=
list_entry
(
tmp
,
struct
urb_priv
,
urb_list
);
out
+=
sprintf
(
out
,
" %d: "
,
++
count
);
out
+=
uhci_show_urbp
(
uhci
,
urbp
,
out
,
len
-
(
out
-
buf
));
tmp
=
tmp
->
next
;
}
}
spin_unlock_irqrestore
(
&
uhci
->
urb_list_lock
,
flags
);
out
+=
sprintf
(
out
,
"Remove list URBs:"
);
spin_lock_irqsave
(
&
uhci
->
urb_remove_list_lock
,
flags
);
if
(
list_empty
(
&
uhci
->
urb_remove_list
))
out
+=
sprintf
(
out
,
" Empty
\n
"
);
else
{
out
+=
sprintf
(
out
,
"
\n
"
);
count
=
0
;
head
=
&
uhci
->
urb_remove_list
;
tmp
=
head
->
next
;
while
(
tmp
!=
head
)
{
struct
urb_priv
*
urbp
=
list_entry
(
tmp
,
struct
urb_priv
,
urb_list
);
out
+=
sprintf
(
out
,
" %d: "
,
++
count
);
out
+=
uhci_show_urbp
(
uhci
,
urbp
,
out
,
len
-
(
out
-
buf
));
tmp
=
tmp
->
next
;
}
}
spin_unlock_irqrestore
(
&
uhci
->
urb_remove_list_lock
,
flags
);
out
+=
sprintf
(
out
,
"Complete list URBs:"
);
spin_lock_irqsave
(
&
uhci
->
complete_list_lock
,
flags
);
if
(
list_empty
(
&
uhci
->
complete_list
))
out
+=
sprintf
(
out
,
" Empty
\n
"
);
else
{
out
+=
sprintf
(
out
,
"
\n
"
);
count
=
0
;
head
=
&
uhci
->
complete_list
;
tmp
=
head
->
next
;
while
(
tmp
!=
head
)
{
struct
urb_priv
*
urbp
=
list_entry
(
tmp
,
struct
urb_priv
,
complete_list
);
out
+=
sprintf
(
out
,
" %d: "
,
++
count
);
out
+=
uhci_show_urbp
(
uhci
,
urbp
,
out
,
len
-
(
out
-
buf
));
tmp
=
tmp
->
next
;
}
}
spin_unlock_irqrestore
(
&
uhci
->
complete_list_lock
,
flags
);
return
out
-
buf
;
}
static
int
uhci_sprint_schedule
(
struct
uhci_hcd
*
uhci
,
char
*
buf
,
int
len
)
static
int
uhci_sprint_schedule
(
struct
uhci_hcd
*
uhci
,
char
*
buf
,
int
len
)
{
{
unsigned
long
flags
;
char
*
out
=
buf
;
char
*
out
=
buf
;
int
i
;
int
i
;
struct
uhci_qh
*
qh
;
struct
uhci_qh
*
qh
;
struct
uhci_td
*
td
;
struct
uhci_td
*
td
;
struct
list_head
*
tmp
,
*
head
;
struct
list_head
*
tmp
,
*
head
;
spin_lock_irqsave
(
&
uhci
->
frame_list_lock
,
flags
);
out
+=
sprintf
(
out
,
"HC status
\n
"
);
out
+=
sprintf
(
out
,
"HC status
\n
"
);
out
+=
uhci_show_status
(
uhci
,
out
,
len
-
(
out
-
buf
));
out
+=
uhci_show_status
(
uhci
,
out
,
len
-
(
out
-
buf
));
...
@@ -333,8 +438,6 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
...
@@ -333,8 +438,6 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
show_frame_num
();
show_frame_num
();
out
+=
sprintf
(
out
,
" frame list does not match td->dma_handle!
\n
"
);
out
+=
sprintf
(
out
,
" frame list does not match td->dma_handle!
\n
"
);
}
}
if
(
uhci_is_skeleton_td
(
uhci
,
td
))
continue
;
show_frame_num
();
show_frame_num
();
head
=
&
td
->
fl_list
;
head
=
&
td
->
fl_list
;
...
@@ -346,67 +449,6 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
...
@@ -346,67 +449,6 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
}
while
(
tmp
!=
head
);
}
while
(
tmp
!=
head
);
}
}
out
+=
sprintf
(
out
,
"Skeleton TD's
\n
"
);
for
(
i
=
UHCI_NUM_SKELTD
-
1
;
i
>=
0
;
i
--
)
{
int
shown
=
0
;
td
=
uhci
->
skeltd
[
i
];
if
(
debug
>
1
)
{
show_td_name
();
out
+=
uhci_show_td
(
td
,
out
,
len
-
(
out
-
buf
),
4
);
}
if
(
list_empty
(
&
td
->
fl_list
))
{
/* TD 0 is the int1 TD and links to control_ls_qh */
if
(
!
i
)
{
if
(
td
->
link
!=
(
cpu_to_le32
(
uhci
->
skel_ls_control_qh
->
dma_handle
)
|
UHCI_PTR_QH
))
{
show_td_name
();
out
+=
sprintf
(
out
,
" skeleton TD not linked to ls_control QH!
\n
"
);
}
}
else
if
(
i
<
9
)
{
if
(
td
->
link
!=
cpu_to_le32
(
uhci
->
skeltd
[
i
-
1
]
->
dma_handle
))
{
show_td_name
();
out
+=
sprintf
(
out
,
" skeleton TD not linked to next skeleton TD!
\n
"
);
}
}
else
{
show_td_name
();
if
(
td
->
link
!=
cpu_to_le32
(
td
->
dma_handle
))
out
+=
sprintf
(
out
,
" skel_term_td does not link to self
\n
"
);
/* Don't show it twice */
if
(
debug
<=
1
)
out
+=
uhci_show_td
(
td
,
out
,
len
-
(
out
-
buf
),
4
);
}
continue
;
}
show_td_name
();
head
=
&
td
->
fl_list
;
tmp
=
head
->
next
;
while
(
tmp
!=
head
)
{
td
=
list_entry
(
tmp
,
struct
uhci_td
,
fl_list
);
tmp
=
tmp
->
next
;
out
+=
uhci_show_td
(
td
,
out
,
len
-
(
out
-
buf
),
4
);
}
if
(
!
i
)
{
if
(
td
->
link
!=
(
cpu_to_le32
(
uhci
->
skel_ls_control_qh
->
dma_handle
)
|
UHCI_PTR_QH
))
out
+=
sprintf
(
out
,
" last TD not linked to ls_control QH!
\n
"
);
}
else
if
(
i
<
9
)
{
if
(
td
->
link
!=
cpu_to_le32
(
uhci
->
skeltd
[
i
-
1
]
->
dma_handle
))
out
+=
sprintf
(
out
,
" last TD not linked to next skeleton!
\n
"
);
}
}
out
+=
sprintf
(
out
,
"Skeleton QH's
\n
"
);
out
+=
sprintf
(
out
,
"Skeleton QH's
\n
"
);
for
(
i
=
0
;
i
<
UHCI_NUM_SKELQH
;
++
i
)
{
for
(
i
=
0
;
i
<
UHCI_NUM_SKELQH
;
++
i
)
{
...
@@ -419,21 +461,19 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
...
@@ -419,21 +461,19 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
out
+=
uhci_show_qh
(
qh
,
out
,
len
-
(
out
-
buf
),
4
);
out
+=
uhci_show_qh
(
qh
,
out
,
len
-
(
out
-
buf
),
4
);
}
}
/* QH 3 is the Terminating QH, it's different */
/* Last QH is the Terminating QH, it's different */
if
(
i
==
3
)
{
if
(
i
==
UHCI_NUM_SKELQH
-
1
)
{
if
(
qh
->
link
!=
UHCI_PTR_TERM
)
{
if
(
qh
->
link
!=
UHCI_PTR_TERM
)
show_qh_name
();
out
+=
sprintf
(
out
,
" bandwidth reclamation on!
\n
"
);
out
+=
sprintf
(
out
,
" bandwidth reclamation on!
\n
"
);
}
if
(
qh
->
element
!=
cpu_to_le32
(
uhci
->
skel_term_td
->
dma_handle
))
{
if
(
qh
->
element
!=
cpu_to_le32
(
uhci
->
term_td
->
dma_handle
))
show_qh_name
(
);
out
+=
sprintf
(
out
,
" skel_term_qh element is not set to term_td!
\n
"
);
out
+=
sprintf
(
out
,
" skel_term_qh element is not set to skel_term_td
\n
"
);
}
continue
;
}
}
if
(
list_empty
(
&
qh
->
list
))
{
if
(
list_empty
(
&
qh
->
list
))
{
if
(
i
<
3
)
{
if
(
i
<
UHCI_NUM_SKELQH
-
1
)
{
if
(
qh
->
link
!=
if
(
qh
->
link
!=
(
cpu_to_le32
(
uhci
->
skelqh
[
i
+
1
]
->
dma_handle
)
|
UHCI_PTR_QH
))
{
(
cpu_to_le32
(
uhci
->
skelqh
[
i
+
1
]
->
dma_handle
)
|
UHCI_PTR_QH
))
{
show_qh_name
();
show_qh_name
();
...
@@ -457,18 +497,23 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
...
@@ -457,18 +497,23 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
out
+=
uhci_show_qh
(
qh
,
out
,
len
-
(
out
-
buf
),
4
);
out
+=
uhci_show_qh
(
qh
,
out
,
len
-
(
out
-
buf
),
4
);
}
}
if
(
i
<
3
)
{
if
(
i
<
UHCI_NUM_SKELQH
-
1
)
{
if
(
qh
->
link
!=
if
(
qh
->
link
!=
(
cpu_to_le32
(
uhci
->
skelqh
[
i
+
1
]
->
dma_handle
)
|
UHCI_PTR_QH
))
(
cpu_to_le32
(
uhci
->
skelqh
[
i
+
1
]
->
dma_handle
)
|
UHCI_PTR_QH
))
out
+=
sprintf
(
out
,
" last QH not linked to next skeleton!
\n
"
);
out
+=
sprintf
(
out
,
" last QH not linked to next skeleton!
\n
"
);
}
}
}
}
spin_unlock_irqrestore
(
&
uhci
->
frame_list_lock
,
flags
);
if
(
debug
>
2
)
out
+=
uhci_show_lists
(
uhci
,
out
,
len
-
(
out
-
buf
));
return
out
-
buf
;
return
out
-
buf
;
}
}
#ifdef CONFIG_PROC_FS
#ifdef CONFIG_PROC_FS
#define MAX_OUTPUT (PAGE_SIZE *
8
)
#define MAX_OUTPUT (PAGE_SIZE *
16
)
static
struct
proc_dir_entry
*
uhci_proc_root
=
NULL
;
static
struct
proc_dir_entry
*
uhci_proc_root
=
NULL
;
...
@@ -483,7 +528,6 @@ static int uhci_proc_open(struct inode *inode, struct file *file)
...
@@ -483,7 +528,6 @@ static int uhci_proc_open(struct inode *inode, struct file *file)
const
struct
proc_dir_entry
*
dp
=
PDE
(
inode
);
const
struct
proc_dir_entry
*
dp
=
PDE
(
inode
);
struct
uhci_hcd
*
uhci
=
dp
->
data
;
struct
uhci_hcd
*
uhci
=
dp
->
data
;
struct
uhci_proc
*
up
;
struct
uhci_proc
*
up
;
unsigned
long
flags
;
int
ret
=
-
ENOMEM
;
int
ret
=
-
ENOMEM
;
lock_kernel
();
lock_kernel
();
...
@@ -497,9 +541,7 @@ static int uhci_proc_open(struct inode *inode, struct file *file)
...
@@ -497,9 +541,7 @@ static int uhci_proc_open(struct inode *inode, struct file *file)
goto
out
;
goto
out
;
}
}
spin_lock_irqsave
(
&
uhci
->
frame_list_lock
,
flags
);
up
->
size
=
uhci_sprint_schedule
(
uhci
,
up
->
data
,
MAX_OUTPUT
);
up
->
size
=
uhci_sprint_schedule
(
uhci
,
up
->
data
,
MAX_OUTPUT
);
spin_unlock_irqrestore
(
&
uhci
->
frame_list_lock
,
flags
);
file
->
private_data
=
up
;
file
->
private_data
=
up
;
...
...
drivers/usb/host/uhci-hcd.c
View file @
2c9fbaf4
...
@@ -69,7 +69,7 @@
...
@@ -69,7 +69,7 @@
* debug = 0, no debugging messages
* debug = 0, no debugging messages
* debug = 1, dump failed URB's except for stalls
* debug = 1, dump failed URB's except for stalls
* debug = 2, dump all failed URB's (including stalls)
* debug = 2, dump all failed URB's (including stalls)
* show all queues in /proc/
uhci/hc*
* show all queues in /proc/
driver/uhci/[pci_addr]
* debug = 3, show all TD's in URB's when dumping
* debug = 3, show all TD's in URB's when dumping
*/
*/
#ifdef DEBUG
#ifdef DEBUG
...
@@ -118,7 +118,7 @@ static inline void uhci_set_next_interrupt(struct uhci_hcd *uhci)
...
@@ -118,7 +118,7 @@ static inline void uhci_set_next_interrupt(struct uhci_hcd *uhci)
unsigned
long
flags
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
uhci
->
frame_list_lock
,
flags
);
spin_lock_irqsave
(
&
uhci
->
frame_list_lock
,
flags
);
uhci
->
skel_
term_td
->
status
|=
cpu_to_le32
(
TD_CTRL_IOC
);
uhci
->
term_td
->
status
|=
cpu_to_le32
(
TD_CTRL_IOC
);
spin_unlock_irqrestore
(
&
uhci
->
frame_list_lock
,
flags
);
spin_unlock_irqrestore
(
&
uhci
->
frame_list_lock
,
flags
);
}
}
...
@@ -127,7 +127,7 @@ static inline void uhci_clear_next_interrupt(struct uhci_hcd *uhci)
...
@@ -127,7 +127,7 @@ static inline void uhci_clear_next_interrupt(struct uhci_hcd *uhci)
unsigned
long
flags
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
uhci
->
frame_list_lock
,
flags
);
spin_lock_irqsave
(
&
uhci
->
frame_list_lock
,
flags
);
uhci
->
skel_
term_td
->
status
&=
~
cpu_to_le32
(
TD_CTRL_IOC
);
uhci
->
term_td
->
status
&=
~
cpu_to_le32
(
TD_CTRL_IOC
);
spin_unlock_irqrestore
(
&
uhci
->
frame_list_lock
,
flags
);
spin_unlock_irqrestore
(
&
uhci
->
frame_list_lock
,
flags
);
}
}
...
@@ -174,30 +174,8 @@ static void inline uhci_fill_td(struct uhci_td *td, __u32 status,
...
@@ -174,30 +174,8 @@ static void inline uhci_fill_td(struct uhci_td *td, __u32 status,
td
->
buffer
=
cpu_to_le32
(
buffer
);
td
->
buffer
=
cpu_to_le32
(
buffer
);
}
}
static
void
uhci_insert_td
(
struct
uhci_hcd
*
uhci
,
struct
uhci_td
*
skeltd
,
struct
uhci_td
*
td
)
{
unsigned
long
flags
;
struct
uhci_td
*
ltd
;
spin_lock_irqsave
(
&
uhci
->
frame_list_lock
,
flags
);
ltd
=
list_entry
(
skeltd
->
fl_list
.
prev
,
struct
uhci_td
,
fl_list
);
td
->
link
=
ltd
->
link
;
mb
();
ltd
->
link
=
cpu_to_le32
(
td
->
dma_handle
);
list_add_tail
(
&
td
->
fl_list
,
&
skeltd
->
fl_list
);
spin_unlock_irqrestore
(
&
uhci
->
frame_list_lock
,
flags
);
}
/*
/*
* We insert Isochronous transfers directly into the frame list at the
* We insert Isochronous URB's directly into the frame list at the beginning
* beginning
* The layout looks as follows:
* frame list pointer -> iso td's (if any) ->
* periodic interrupt td (if frame 0) -> irq td's -> control qh -> bulk qh
*/
*/
static
void
uhci_insert_td_frame_list
(
struct
uhci_hcd
*
uhci
,
struct
uhci_td
*
td
,
unsigned
framenum
)
static
void
uhci_insert_td_frame_list
(
struct
uhci_hcd
*
uhci
,
struct
uhci_td
*
td
,
unsigned
framenum
)
{
{
...
@@ -374,8 +352,9 @@ static void _uhci_insert_qh(struct uhci_hcd *uhci, struct uhci_qh *skelqh, struc
...
@@ -374,8 +352,9 @@ static void _uhci_insert_qh(struct uhci_hcd *uhci, struct uhci_qh *skelqh, struc
/* Grab the last QH */
/* Grab the last QH */
lqh
=
list_entry
(
skelqh
->
list
.
prev
,
struct
uhci_qh
,
list
);
lqh
=
list_entry
(
skelqh
->
list
.
prev
,
struct
uhci_qh
,
list
);
/* Patch this endpoint's URBs' QHs to point to the next skelQH:
/*
* SkelQH --> ... lqh --> NewQH --> NextSkelQH
* Patch this endpoint's URB's QHs to point to the next skelqh:
* skelqh --> ... lqh --> newqh --> next skelqh
* Do this first, so the HC always sees the right QH after this one.
* Do this first, so the HC always sees the right QH after this one.
*/
*/
list_for_each
(
tmp
,
&
urbp
->
queue_list
)
{
list_for_each
(
tmp
,
&
urbp
->
queue_list
)
{
...
@@ -387,15 +366,16 @@ static void _uhci_insert_qh(struct uhci_hcd *uhci, struct uhci_qh *skelqh, struc
...
@@ -387,15 +366,16 @@ static void _uhci_insert_qh(struct uhci_hcd *uhci, struct uhci_qh *skelqh, struc
urbp
->
qh
->
link
=
lqh
->
link
;
urbp
->
qh
->
link
=
lqh
->
link
;
wmb
();
/* Ordering is important */
wmb
();
/* Ordering is important */
/* Patch QHs for previous endpoint's queued URBs? HC goes
/*
* here next, not to the NextSkelQH it now points to.
* Patch QHs for previous endpoint's queued URBs? HC goes
* here next, not to the next skelqh it now points to.
*
*
* lqh --> td ... --> qh ... --> td --> qh ... --> td
* lqh --> td ... --> qh ... --> td --> qh ... --> td
* | | |
* | | |
* v v v
* v v v
* +<----------------+-----------------+
* +<----------------+-----------------+
* v
* v
*
NewQH
--> td ... --> td
*
newqh
--> td ... --> td
* |
* |
* v
* v
* ...
* ...
...
@@ -424,7 +404,8 @@ static void uhci_insert_qh(struct uhci_hcd *uhci, struct uhci_qh *skelqh, struct
...
@@ -424,7 +404,8 @@ static void uhci_insert_qh(struct uhci_hcd *uhci, struct uhci_qh *skelqh, struct
spin_unlock_irqrestore
(
&
uhci
->
frame_list_lock
,
flags
);
spin_unlock_irqrestore
(
&
uhci
->
frame_list_lock
,
flags
);
}
}
/* start removal of qh from schedule; it finishes next frame.
/*
* Start removal of QH from schedule; it finishes next frame.
* TDs should be unlinked before this is called.
* TDs should be unlinked before this is called.
*/
*/
static
void
uhci_remove_qh
(
struct
uhci_hcd
*
uhci
,
struct
uhci_qh
*
qh
)
static
void
uhci_remove_qh
(
struct
uhci_hcd
*
uhci
,
struct
uhci_qh
*
qh
)
...
@@ -437,7 +418,12 @@ static void uhci_remove_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
...
@@ -437,7 +418,12 @@ static void uhci_remove_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
qh
->
urbp
=
NULL
;
qh
->
urbp
=
NULL
;
/* Only go through the hoops if it's actually linked in */
/*
* Only go through the hoops if it's actually linked in
* Queued QHs are removed in uhci_delete_queued_urb,
* since (for queued URBs) the pqh is pointed to the next
* QH in the queue, not the next endpoint's QH.
*/
spin_lock_irqsave
(
&
uhci
->
frame_list_lock
,
flags
);
spin_lock_irqsave
(
&
uhci
->
frame_list_lock
,
flags
);
if
(
!
list_empty
(
&
qh
->
list
))
{
if
(
!
list_empty
(
&
qh
->
list
))
{
pqh
=
list_entry
(
qh
->
list
.
prev
,
struct
uhci_qh
,
list
);
pqh
=
list_entry
(
qh
->
list
.
prev
,
struct
uhci_qh
,
list
);
...
@@ -459,7 +445,9 @@ static void uhci_remove_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
...
@@ -459,7 +445,9 @@ static void uhci_remove_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
pqh
->
link
=
qh
->
link
;
pqh
->
link
=
qh
->
link
;
mb
();
mb
();
qh
->
element
=
qh
->
link
=
UHCI_PTR_TERM
;
/* Leave qh->link in case the HC is on the QH now, it will */
/* continue the rest of the schedule */
qh
->
element
=
UHCI_PTR_TERM
;
list_del_init
(
&
qh
->
list
);
list_del_init
(
&
qh
->
list
);
}
}
...
@@ -502,8 +490,7 @@ static int uhci_fixup_toggle(struct urb *urb, unsigned int toggle)
...
@@ -502,8 +490,7 @@ static int uhci_fixup_toggle(struct urb *urb, unsigned int toggle)
}
}
/* This function will append one URB's QH to another URB's QH. This is for */
/* This function will append one URB's QH to another URB's QH. This is for */
/* queuing bulk transfers and soon implicitily for */
/* queuing interrupt, control or bulk transfers */
/* control transfers */
static
void
uhci_append_queued_urb
(
struct
uhci_hcd
*
uhci
,
struct
urb
*
eurb
,
struct
urb
*
urb
)
static
void
uhci_append_queued_urb
(
struct
uhci_hcd
*
uhci
,
struct
urb
*
eurb
,
struct
urb
*
urb
)
{
{
struct
urb_priv
*
eurbp
,
*
urbp
,
*
furbp
,
*
lurbp
;
struct
urb_priv
*
eurbp
,
*
urbp
,
*
furbp
,
*
lurbp
;
...
@@ -545,7 +532,7 @@ static void uhci_append_queued_urb(struct uhci_hcd *uhci, struct urb *eurb, stru
...
@@ -545,7 +532,7 @@ static void uhci_append_queued_urb(struct uhci_hcd *uhci, struct urb *eurb, stru
urbp
->
qh
->
link
=
eurbp
->
qh
->
link
;
urbp
->
qh
->
link
=
eurbp
->
qh
->
link
;
mb
();
/* Make sure we flush everything */
mb
();
/* Make sure we flush everything */
/* Only support bulk right now, so no depth */
lltd
->
link
=
cpu_to_le32
(
urbp
->
qh
->
dma_handle
)
|
UHCI_PTR_QH
;
lltd
->
link
=
cpu_to_le32
(
urbp
->
qh
->
dma_handle
)
|
UHCI_PTR_QH
;
list_add_tail
(
&
urbp
->
queue_list
,
&
furbp
->
queue_list
);
list_add_tail
(
&
urbp
->
queue_list
,
&
furbp
->
queue_list
);
...
@@ -575,7 +562,7 @@ static void uhci_delete_queued_urb(struct uhci_hcd *uhci, struct urb *urb)
...
@@ -575,7 +562,7 @@ static void uhci_delete_queued_urb(struct uhci_hcd *uhci, struct urb *urb)
/* Fix up the toggle for the next URB's */
/* Fix up the toggle for the next URB's */
if
(
!
urbp
->
queued
)
if
(
!
urbp
->
queued
)
/* We
set the toggle when we unlink
*/
/* We
just set the toggle in uhci_unlink_generic
*/
toggle
=
usb_gettoggle
(
urb
->
dev
,
usb_pipeendpoint
(
urb
->
pipe
),
usb_pipeout
(
urb
->
pipe
));
toggle
=
usb_gettoggle
(
urb
->
dev
,
usb_pipeendpoint
(
urb
->
pipe
),
usb_pipeout
(
urb
->
pipe
));
else
{
else
{
/* If we're in the middle of the queue, grab the toggle */
/* If we're in the middle of the queue, grab the toggle */
...
@@ -607,9 +594,35 @@ static void uhci_delete_queued_urb(struct uhci_hcd *uhci, struct urb *urb)
...
@@ -607,9 +594,35 @@ static void uhci_delete_queued_urb(struct uhci_hcd *uhci, struct urb *urb)
usb_pipeout
(
urb
->
pipe
),
toggle
);
usb_pipeout
(
urb
->
pipe
),
toggle
);
if
(
!
urbp
->
queued
)
{
if
(
!
urbp
->
queued
)
{
struct
uhci_qh
*
pqh
;
nurbp
->
queued
=
0
;
nurbp
->
queued
=
0
;
_uhci_insert_qh
(
uhci
,
uhci
->
skel_bulk_qh
,
nurbp
->
urb
);
/*
* Fixup the previous QH's queue to link to the new head
* of this queue.
*/
pqh
=
list_entry
(
urbp
->
qh
->
list
.
prev
,
struct
uhci_qh
,
list
);
if
(
pqh
->
urbp
)
{
struct
list_head
*
head
,
*
tmp
;
head
=
&
pqh
->
urbp
->
queue_list
;
tmp
=
head
->
next
;
while
(
head
!=
tmp
)
{
struct
urb_priv
*
turbp
=
list_entry
(
tmp
,
struct
urb_priv
,
queue_list
);
tmp
=
tmp
->
next
;
turbp
->
qh
->
link
=
cpu_to_le32
(
nurbp
->
qh
->
dma_handle
)
|
UHCI_PTR_QH
;
}
}
pqh
->
link
=
cpu_to_le32
(
nurbp
->
qh
->
dma_handle
)
|
UHCI_PTR_QH
;
list_add_tail
(
&
nurbp
->
qh
->
list
,
&
urbp
->
qh
->
list
);
list_del_init
(
&
urbp
->
qh
->
list
);
}
else
{
}
else
{
/* We're somewhere in the middle (or end). A bit trickier */
/* We're somewhere in the middle (or end). A bit trickier */
/* than the head scenario */
/* than the head scenario */
...
@@ -786,11 +799,11 @@ static int uhci_map_status(int status, int dir_out)
...
@@ -786,11 +799,11 @@ static int uhci_map_status(int status, int dir_out)
/*
/*
* Control transfers
* Control transfers
*/
*/
static
int
uhci_submit_control
(
struct
uhci_hcd
*
uhci
,
struct
urb
*
urb
)
static
int
uhci_submit_control
(
struct
uhci_hcd
*
uhci
,
struct
urb
*
urb
,
struct
urb
*
eurb
)
{
{
struct
urb_priv
*
urbp
=
(
struct
urb_priv
*
)
urb
->
hcpriv
;
struct
urb_priv
*
urbp
=
(
struct
urb_priv
*
)
urb
->
hcpriv
;
struct
uhci_td
*
td
;
struct
uhci_td
*
td
;
struct
uhci_qh
*
qh
;
struct
uhci_qh
*
qh
,
*
skelqh
;
unsigned
long
destination
,
status
;
unsigned
long
destination
,
status
;
int
maxsze
=
usb_maxpacket
(
urb
->
dev
,
urb
->
pipe
,
usb_pipeout
(
urb
->
pipe
));
int
maxsze
=
usb_maxpacket
(
urb
->
dev
,
urb
->
pipe
,
usb_pipeout
(
urb
->
pipe
));
int
len
=
urb
->
transfer_buffer_length
;
int
len
=
urb
->
transfer_buffer_length
;
...
@@ -880,19 +893,32 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb)
...
@@ -880,19 +893,32 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb)
urbp
->
qh
=
qh
;
urbp
->
qh
=
qh
;
qh
->
urbp
=
urbp
;
qh
->
urbp
=
urbp
;
/* Low speed transfers get a different queue, and won't hog the bus */
if
(
urb
->
dev
->
speed
==
USB_SPEED_LOW
)
{
uhci_insert_tds_in_qh
(
qh
,
urb
,
UHCI_PTR_DEPTH
);
uhci_insert_qh
(
uhci
,
uhci
->
skel_ls_control_qh
,
urb
);
}
else
{
uhci_insert_tds_in_qh
(
qh
,
urb
,
UHCI_PTR_BREADTH
);
uhci_insert_tds_in_qh
(
qh
,
urb
,
UHCI_PTR_BREADTH
);
uhci_insert_qh
(
uhci
,
uhci
->
skel_hs_control_qh
,
urb
);
/* Low speed transfers get a different queue, and won't hog the bus */
if
(
urb
->
dev
->
speed
==
USB_SPEED_LOW
)
skelqh
=
uhci
->
skel_ls_control_qh
;
else
{
skelqh
=
uhci
->
skel_hs_control_qh
;
uhci_inc_fsbr
(
uhci
,
urb
);
uhci_inc_fsbr
(
uhci
,
urb
);
}
}
if
(
eurb
)
uhci_append_queued_urb
(
uhci
,
eurb
,
urb
);
else
uhci_insert_qh
(
uhci
,
skelqh
,
urb
);
return
-
EINPROGRESS
;
return
-
EINPROGRESS
;
}
}
/*
* If control was short, then end status packet wasn't sent, so this
* reorganize s so it's sent to finish the transfer. The original QH is
* removed from the skel and discarded; all TDs except the last (status)
* are deleted; the last (status) TD is put on a new QH which is reinserted
* into the skel. Since the last TD and urb_priv are reused, the TD->link
* and urb_priv maintain any queued QHs.
*/
static
int
usb_control_retrigger_status
(
struct
uhci_hcd
*
uhci
,
struct
urb
*
urb
)
static
int
usb_control_retrigger_status
(
struct
uhci_hcd
*
uhci
,
struct
urb
*
urb
)
{
{
struct
list_head
*
tmp
,
*
head
;
struct
list_head
*
tmp
,
*
head
;
...
@@ -1047,46 +1073,109 @@ static int uhci_result_control(struct uhci_hcd *uhci, struct urb *urb)
...
@@ -1047,46 +1073,109 @@ static int uhci_result_control(struct uhci_hcd *uhci, struct urb *urb)
}
}
/*
/*
*
Interrupt transfers
*
Common submit for bulk and interrupt
*/
*/
static
int
uhci_submit_
interrupt
(
struct
uhci_hcd
*
uhci
,
struct
urb
*
urb
)
static
int
uhci_submit_
common
(
struct
uhci_hcd
*
uhci
,
struct
urb
*
urb
,
struct
urb
*
eurb
,
struct
uhci_qh
*
skelqh
)
{
{
struct
uhci_td
*
td
;
struct
uhci_td
*
td
;
struct
uhci_qh
*
qh
;
unsigned
long
destination
,
status
;
unsigned
long
destination
,
status
;
int
maxsze
=
usb_maxpacket
(
urb
->
dev
,
urb
->
pipe
,
usb_pipeout
(
urb
->
pipe
));
int
len
=
urb
->
transfer_buffer_length
;
struct
urb_priv
*
urbp
=
(
struct
urb_priv
*
)
urb
->
hcpriv
;
dma_addr_t
data
=
urb
->
transfer_dma
;
if
(
urb
->
transfer_buffer_length
>
usb_maxpacket
(
urb
->
dev
,
urb
->
pipe
,
usb_pipeout
(
urb
->
pipe
))
)
if
(
len
<
0
)
return
-
EINVAL
;
return
-
EINVAL
;
/* The "pipe" thing contains the destination in bits 8--18 */
/* The "pipe" thing contains the destination in bits 8--18 */
destination
=
(
urb
->
pipe
&
PIPE_DEVEP_MASK
)
|
usb_packetid
(
urb
->
pipe
);
destination
=
(
urb
->
pipe
&
PIPE_DEVEP_MASK
)
|
usb_packetid
(
urb
->
pipe
);
status
=
TD_CTRL_ACTIVE
|
TD_CTRL_IOC
;
status
=
uhci_maxerr
(
3
)
|
TD_CTRL_ACTIVE
;
if
(
urb
->
dev
->
speed
==
USB_SPEED_LOW
)
if
(
urb
->
dev
->
speed
==
USB_SPEED_LOW
)
status
|=
TD_CTRL_LS
;
status
|=
TD_CTRL_LS
;
if
(
!
(
urb
->
transfer_flags
&
URB_SHORT_NOT_OK
))
status
|=
TD_CTRL_SPD
;
/*
* Build the DATA TD's
*/
do
{
/* Allow zero length packets */
int
pktsze
=
len
;
if
(
pktsze
>
maxsze
)
pktsze
=
maxsze
;
td
=
uhci_alloc_td
(
uhci
,
urb
->
dev
);
td
=
uhci_alloc_td
(
uhci
,
urb
->
dev
);
if
(
!
td
)
if
(
!
td
)
return
-
ENOMEM
;
return
-
ENOMEM
;
destination
|=
(
usb_gettoggle
(
urb
->
dev
,
usb_pipeendpoint
(
urb
->
pipe
),
usb_pipeout
(
urb
->
pipe
))
<<
TD_TOKEN_TOGGLE_SHIFT
);
uhci_add_td_to_urb
(
urb
,
td
);
destination
|=
uhci_explen
(
urb
->
transfer_buffer_length
-
1
);
uhci_fill_td
(
td
,
status
,
destination
|
uhci_explen
(
pktsze
-
1
)
|
(
usb_gettoggle
(
urb
->
dev
,
usb_pipeendpoint
(
urb
->
pipe
),
usb_pipeout
(
urb
->
pipe
))
<<
TD_TOKEN_TOGGLE_SHIFT
),
data
);
data
+=
pktsze
;
len
-=
maxsze
;
usb_dotoggle
(
urb
->
dev
,
usb_pipeendpoint
(
urb
->
pipe
),
usb_pipeout
(
urb
->
pipe
));
usb_dotoggle
(
urb
->
dev
,
usb_pipeendpoint
(
urb
->
pipe
),
usb_pipeout
(
urb
->
pipe
));
}
while
(
len
>
0
);
/*
* USB_ZERO_PACKET means adding a 0-length packet, if direction
* is OUT and the transfer_length was an exact multiple of maxsze,
* hence (len = transfer_length - N * maxsze) == 0
* however, if transfer_length == 0, the zero packet was already
* prepared above.
*/
if
(
usb_pipeout
(
urb
->
pipe
)
&&
(
urb
->
transfer_flags
&
USB_ZERO_PACKET
)
&&
!
len
&&
urb
->
transfer_buffer_length
)
{
td
=
uhci_alloc_td
(
uhci
,
urb
->
dev
);
if
(
!
td
)
return
-
ENOMEM
;
uhci_add_td_to_urb
(
urb
,
td
);
uhci_add_td_to_urb
(
urb
,
td
);
uhci_fill_td
(
td
,
status
,
destination
,
urb
->
transfer_dma
);
uhci_fill_td
(
td
,
status
,
destination
|
uhci_explen
(
UHCI_NULL_DATA_SIZE
)
|
(
usb_gettoggle
(
urb
->
dev
,
usb_pipeendpoint
(
urb
->
pipe
),
usb_pipeout
(
urb
->
pipe
))
<<
TD_TOKEN_TOGGLE_SHIFT
),
data
);
uhci_insert_td
(
uhci
,
uhci
->
skeltd
[
__interval_to_skel
(
urb
->
interval
)],
td
);
usb_dotoggle
(
urb
->
dev
,
usb_pipeendpoint
(
urb
->
pipe
),
usb_pipeout
(
urb
->
pipe
));
}
/* Set the flag on the last packet */
td
->
status
|=
cpu_to_le32
(
TD_CTRL_IOC
);
qh
=
uhci_alloc_qh
(
uhci
,
urb
->
dev
);
if
(
!
qh
)
return
-
ENOMEM
;
urbp
->
qh
=
qh
;
qh
->
urbp
=
urbp
;
/* Always breadth first */
uhci_insert_tds_in_qh
(
qh
,
urb
,
UHCI_PTR_BREADTH
);
if
(
eurb
)
uhci_append_queued_urb
(
uhci
,
eurb
,
urb
);
else
uhci_insert_qh
(
uhci
,
skelqh
,
urb
);
return
-
EINPROGRESS
;
return
-
EINPROGRESS
;
}
}
static
int
uhci_result_interrupt
(
struct
uhci_hcd
*
uhci
,
struct
urb
*
urb
)
/*
* Common result for bulk and interrupt
*/
static
int
uhci_result_common
(
struct
uhci_hcd
*
uhci
,
struct
urb
*
urb
)
{
{
struct
list_head
*
tmp
,
*
head
;
struct
list_head
*
tmp
,
*
head
;
struct
urb_priv
*
urbp
=
urb
->
hcpriv
;
struct
urb_priv
*
urbp
=
urb
->
hcpriv
;
struct
uhci_td
*
td
;
struct
uhci_td
*
td
;
unsigned
int
status
;
unsigned
int
status
=
0
;
int
ret
=
0
;
int
ret
=
0
;
urb
->
actual_length
=
0
;
urb
->
actual_length
=
0
;
...
@@ -1128,15 +1217,11 @@ static int uhci_result_interrupt(struct uhci_hcd *uhci, struct urb *urb)
...
@@ -1128,15 +1217,11 @@ static int uhci_result_interrupt(struct uhci_hcd *uhci, struct urb *urb)
err:
err:
if
((
debug
==
1
&&
ret
!=
-
EPIPE
)
||
debug
>
1
)
{
if
((
debug
==
1
&&
ret
!=
-
EPIPE
)
||
debug
>
1
)
{
/* Some debugging code */
/* Some debugging code */
dbg
(
"uhci_result_interrupt/bulk() failed with status %x"
,
dbg
(
"uhci_result_common() failed with status %x"
,
status
);
status
);
if
(
errbuf
)
{
if
(
errbuf
)
{
/* Print the chain for debugging purposes */
/* Print the chain for debugging purposes */
if
(
urbp
->
qh
)
uhci_show_qh
(
urbp
->
qh
,
errbuf
,
ERRBUF_LEN
,
0
);
uhci_show_qh
(
urbp
->
qh
,
errbuf
,
ERRBUF_LEN
,
0
);
else
uhci_show_td
(
td
,
errbuf
,
ERRBUF_LEN
,
0
);
lprintk
(
errbuf
);
lprintk
(
errbuf
);
}
}
...
@@ -1145,129 +1230,35 @@ static int uhci_result_interrupt(struct uhci_hcd *uhci, struct urb *urb)
...
@@ -1145,129 +1230,35 @@ static int uhci_result_interrupt(struct uhci_hcd *uhci, struct urb *urb)
return
ret
;
return
ret
;
}
}
static
void
uhci_reset_interrupt
(
struct
uhci_hcd
*
uhci
,
struct
urb
*
urb
)
static
inline
int
uhci_submit_bulk
(
struct
uhci_hcd
*
uhci
,
struct
urb
*
urb
,
struct
urb
*
e
urb
)
{
{
struct
urb_priv
*
urbp
=
(
struct
urb_priv
*
)
urb
->
hcpriv
;
int
ret
;
struct
uhci_td
*
td
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
urb
->
lock
,
flags
);
td
=
list_entry
(
urbp
->
td_list
.
next
,
struct
uhci_td
,
list
);
td
->
status
=
(
td
->
status
&
cpu_to_le32
(
0x2F000000
))
|
cpu_to_le32
(
TD_CTRL_ACTIVE
|
TD_CTRL_IOC
);
td
->
token
&=
~
cpu_to_le32
(
TD_TOKEN_TOGGLE
);
td
->
token
|=
cpu_to_le32
(
usb_gettoggle
(
urb
->
dev
,
usb_pipeendpoint
(
urb
->
pipe
),
usb_pipeout
(
urb
->
pipe
))
<<
TD_TOKEN_TOGGLE_SHIFT
);
usb_dotoggle
(
urb
->
dev
,
usb_pipeendpoint
(
urb
->
pipe
),
usb_pipeout
(
urb
->
pipe
));
urb
->
status
=
-
EINPROGRESS
;
spin_unlock_irqrestore
(
&
urb
->
lock
,
flags
);
}
/*
* Bulk transfers
*/
static
int
uhci_submit_bulk
(
struct
uhci_hcd
*
uhci
,
struct
urb
*
urb
,
struct
urb
*
eurb
)
{
struct
uhci_td
*
td
;
struct
uhci_qh
*
qh
;
unsigned
long
destination
,
status
;
int
maxsze
=
usb_maxpacket
(
urb
->
dev
,
urb
->
pipe
,
usb_pipeout
(
urb
->
pipe
));
int
len
=
urb
->
transfer_buffer_length
;
struct
urb_priv
*
urbp
=
(
struct
urb_priv
*
)
urb
->
hcpriv
;
dma_addr_t
data
=
urb
->
transfer_dma
;
if
(
len
<
0
)
return
-
EINVAL
;
/* Can't have low speed bulk transfers */
/* Can't have low speed bulk transfers */
if
(
urb
->
dev
->
speed
==
USB_SPEED_LOW
)
if
(
urb
->
dev
->
speed
==
USB_SPEED_LOW
)
return
-
EINVAL
;
return
-
EINVAL
;
/* The "pipe" thing contains the destination in bits 8--18 */
ret
=
uhci_submit_common
(
uhci
,
urb
,
eurb
,
uhci
->
skel_bulk_qh
);
destination
=
(
urb
->
pipe
&
PIPE_DEVEP_MASK
)
|
usb_packetid
(
urb
->
pipe
);
if
(
ret
==
-
EINPROGRESS
)
uhci_inc_fsbr
(
uhci
,
urb
);
/* 3 errors */
status
=
TD_CTRL_ACTIVE
|
uhci_maxerr
(
3
);
if
(
!
(
urb
->
transfer_flags
&
URB_SHORT_NOT_OK
))
status
|=
TD_CTRL_SPD
;
/*
* Build the DATA TD's
*/
do
{
/* Allow zero length packets */
int
pktsze
=
len
;
if
(
pktsze
>
maxsze
)
pktsze
=
maxsze
;
td
=
uhci_alloc_td
(
uhci
,
urb
->
dev
);
if
(
!
td
)
return
-
ENOMEM
;
uhci_add_td_to_urb
(
urb
,
td
);
uhci_fill_td
(
td
,
status
,
destination
|
uhci_explen
(
pktsze
-
1
)
|
(
usb_gettoggle
(
urb
->
dev
,
usb_pipeendpoint
(
urb
->
pipe
),
usb_pipeout
(
urb
->
pipe
))
<<
TD_TOKEN_TOGGLE_SHIFT
),
data
);
data
+=
pktsze
;
len
-=
maxsze
;
usb_dotoggle
(
urb
->
dev
,
usb_pipeendpoint
(
urb
->
pipe
),
usb_pipeout
(
urb
->
pipe
));
}
while
(
len
>
0
);
/*
* USB_ZERO_PACKET means adding a 0-length packet, if
* direction is OUT and the transfer_length was an
* exact multiple of maxsze, hence
* (len = transfer_length - N * maxsze) == 0
* however, if transfer_length == 0, the zero packet
* was already prepared above.
*/
if
(
usb_pipeout
(
urb
->
pipe
)
&&
(
urb
->
transfer_flags
&
USB_ZERO_PACKET
)
&&
!
len
&&
urb
->
transfer_buffer_length
)
{
td
=
uhci_alloc_td
(
uhci
,
urb
->
dev
);
if
(
!
td
)
return
-
ENOMEM
;
uhci_add_td_to_urb
(
urb
,
td
);
uhci_fill_td
(
td
,
status
,
destination
|
uhci_explen
(
UHCI_NULL_DATA_SIZE
)
|
(
usb_gettoggle
(
urb
->
dev
,
usb_pipeendpoint
(
urb
->
pipe
),
usb_pipeout
(
urb
->
pipe
))
<<
TD_TOKEN_TOGGLE_SHIFT
),
data
);
usb_dotoggle
(
urb
->
dev
,
usb_pipeendpoint
(
urb
->
pipe
),
usb_pipeout
(
urb
->
pipe
));
}
/* Set the flag on the last packet */
td
->
status
|=
cpu_to_le32
(
TD_CTRL_IOC
);
qh
=
uhci_alloc_qh
(
uhci
,
urb
->
dev
);
if
(
!
qh
)
return
-
ENOMEM
;
urbp
->
qh
=
qh
;
qh
->
urbp
=
urbp
;
/* Always breadth first */
uhci_insert_tds_in_qh
(
qh
,
urb
,
UHCI_PTR_BREADTH
);
if
(
eurb
)
return
ret
;
uhci_append_queued_urb
(
uhci
,
eurb
,
urb
);
}
else
uhci_insert_qh
(
uhci
,
uhci
->
skel_bulk_qh
,
urb
);
uhci_inc_fsbr
(
uhci
,
urb
);
static
inline
int
uhci_submit_interrupt
(
struct
uhci_hcd
*
uhci
,
struct
urb
*
urb
,
struct
urb
*
eurb
)
{
/* Interrupt-IN can't be more than 1 packet */
if
(
usb_pipein
(
urb
->
pipe
)
&&
urb
->
transfer_buffer_length
>
usb_maxpacket
(
urb
->
dev
,
urb
->
pipe
,
usb_pipeout
(
urb
->
pipe
)))
return
-
EINVAL
;
return
-
EINPROGRESS
;
return
uhci_submit_common
(
uhci
,
urb
,
eurb
,
uhci
->
skelqh
[
__interval_to_skel
(
urb
->
interval
)])
;
}
}
/* We can use the result interrupt since they're identical */
/*
#define uhci_result_bulk uhci_result_interrupt
* Bulk and interrupt use common result
*/
#define uhci_result_bulk uhci_result_common
#define uhci_result_interrupt uhci_result_common
/*
/*
* Isochronous transfers
* Isochronous transfers
...
@@ -1457,31 +1448,27 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, int mem_flags)
...
@@ -1457,31 +1448,27 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, int mem_flags)
switch
(
usb_pipetype
(
urb
->
pipe
))
{
switch
(
usb_pipetype
(
urb
->
pipe
))
{
case
PIPE_CONTROL
:
case
PIPE_CONTROL
:
if
(
eurb
)
ret
=
uhci_submit_control
(
uhci
,
urb
,
eurb
);
ret
=
-
ENXIO
;
/* no control queueing yet */
else
ret
=
uhci_submit_control
(
uhci
,
urb
);
break
;
break
;
case
PIPE_INTERRUPT
:
case
PIPE_INTERRUPT
:
if
(
eurb
)
if
(
!
eurb
)
{
ret
=
-
ENXIO
;
/* no interrupt queueing yet */
else
if
(
urb
->
bandwidth
==
0
)
{
/* not yet checked/allocated */
bustime
=
usb_check_bandwidth
(
urb
->
dev
,
urb
);
bustime
=
usb_check_bandwidth
(
urb
->
dev
,
urb
);
if
(
bustime
<
0
)
if
(
bustime
<
0
)
ret
=
bustime
;
ret
=
bustime
;
else
{
else
{
ret
=
uhci_submit_interrupt
(
uhci
,
urb
);
ret
=
uhci_submit_interrupt
(
uhci
,
urb
,
eurb
);
if
(
ret
==
-
EINPROGRESS
)
if
(
ret
==
-
EINPROGRESS
)
usb_claim_bandwidth
(
urb
->
dev
,
urb
,
bustime
,
0
);
usb_claim_bandwidth
(
urb
->
dev
,
urb
,
bustime
,
0
);
}
}
}
else
/* bandwidth is already set */
}
else
{
/* inherit from parent */
ret
=
uhci_submit_interrupt
(
uhci
,
urb
);
urb
->
bandwidth
=
eurb
->
bandwidth
;
ret
=
uhci_submit_interrupt
(
uhci
,
urb
,
eurb
);
}
break
;
break
;
case
PIPE_BULK
:
case
PIPE_BULK
:
ret
=
uhci_submit_bulk
(
uhci
,
urb
,
eurb
);
ret
=
uhci_submit_bulk
(
uhci
,
urb
,
eurb
);
break
;
break
;
case
PIPE_ISOCHRONOUS
:
case
PIPE_ISOCHRONOUS
:
if
(
urb
->
bandwidth
==
0
)
{
/* not yet checked/allocated */
bustime
=
usb_check_bandwidth
(
urb
->
dev
,
urb
);
bustime
=
usb_check_bandwidth
(
urb
->
dev
,
urb
);
if
(
bustime
<
0
)
{
if
(
bustime
<
0
)
{
ret
=
bustime
;
ret
=
bustime
;
...
@@ -1491,17 +1478,22 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, int mem_flags)
...
@@ -1491,17 +1478,22 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, int mem_flags)
ret
=
uhci_submit_isochronous
(
uhci
,
urb
);
ret
=
uhci_submit_isochronous
(
uhci
,
urb
);
if
(
ret
==
-
EINPROGRESS
)
if
(
ret
==
-
EINPROGRESS
)
usb_claim_bandwidth
(
urb
->
dev
,
urb
,
bustime
,
1
);
usb_claim_bandwidth
(
urb
->
dev
,
urb
,
bustime
,
1
);
}
else
/* bandwidth is already set */
ret
=
uhci_submit_isochronous
(
uhci
,
urb
);
break
;
break
;
}
}
spin_unlock_irqrestore
(
&
uhci
->
urb_list_lock
,
flags
);
if
(
ret
!=
-
EINPROGRESS
)
{
if
(
ret
!=
-
EINPROGRESS
)
{
/* Submit failed, so delete it from the urb_list */
struct
urb_priv
*
urbp
=
urb
->
hcpriv
;
list_del_init
(
&
urbp
->
urb_list
);
spin_unlock_irqrestore
(
&
uhci
->
urb_list_lock
,
flags
);
uhci_destroy_urb_priv
(
uhci
,
urb
);
uhci_destroy_urb_priv
(
uhci
,
urb
);
return
ret
;
return
ret
;
}
}
spin_unlock_irqrestore
(
&
uhci
->
urb_list_lock
,
flags
);
return
0
;
return
0
;
}
}
...
@@ -1556,14 +1548,17 @@ static void uhci_transfer_result(struct uhci_hcd *uhci, struct urb *urb)
...
@@ -1556,14 +1548,17 @@ static void uhci_transfer_result(struct uhci_hcd *uhci, struct urb *urb)
uhci_unlink_generic
(
uhci
,
urb
);
uhci_unlink_generic
(
uhci
,
urb
);
break
;
break
;
case
PIPE_INTERRUPT
:
case
PIPE_INTERRUPT
:
/* Interrupts are an exception */
if
(
urb
->
interval
)
goto
out_complete
;
/* Release bandwidth for Interrupt or Isoc. transfers */
/* Release bandwidth for Interrupt or Isoc. transfers */
/* Make sure we don't release if we have a queued URB */
spin_lock
(
&
uhci
->
frame_list_lock
);
/* Spinlock needed ? */
/* Spinlock needed ? */
if
(
urb
->
bandwidth
)
if
(
list_empty
(
&
urbp
->
queue_list
)
&&
urb
->
bandwidth
)
usb_release_bandwidth
(
urb
->
dev
,
urb
,
0
);
usb_release_bandwidth
(
urb
->
dev
,
urb
,
0
);
else
/* bandwidth was passed on to queued URB, */
/* so don't let usb_unlink_urb() release it */
urb
->
bandwidth
=
0
;
spin_unlock
(
&
uhci
->
frame_list_lock
);
uhci_unlink_generic
(
uhci
,
urb
);
uhci_unlink_generic
(
uhci
,
urb
);
break
;
break
;
default:
default:
...
@@ -1574,7 +1569,6 @@ static void uhci_transfer_result(struct uhci_hcd *uhci, struct urb *urb)
...
@@ -1574,7 +1569,6 @@ static void uhci_transfer_result(struct uhci_hcd *uhci, struct urb *urb)
/* Remove it from uhci->urb_list */
/* Remove it from uhci->urb_list */
list_del_init
(
&
urbp
->
urb_list
);
list_del_init
(
&
urbp
->
urb_list
);
out_complete:
uhci_add_complete
(
uhci
,
urb
);
uhci_add_complete
(
uhci
,
urb
);
out:
out:
...
@@ -1643,6 +1637,13 @@ static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
...
@@ -1643,6 +1637,13 @@ static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
unsigned
long
flags
;
unsigned
long
flags
;
struct
urb_priv
*
urbp
=
urb
->
hcpriv
;
struct
urb_priv
*
urbp
=
urb
->
hcpriv
;
/* If this is an interrupt URB that is being killed in urb->complete, */
/* then just set its status and return */
if
(
!
urbp
)
{
urb
->
status
=
-
ECONNRESET
;
return
0
;
}
spin_lock_irqsave
(
&
uhci
->
urb_list_lock
,
flags
);
spin_lock_irqsave
(
&
uhci
->
urb_list_lock
,
flags
);
list_del_init
(
&
urbp
->
urb_list
);
list_del_init
(
&
urbp
->
urb_list
);
...
@@ -1805,38 +1806,42 @@ static void uhci_finish_urb(struct usb_hcd *hcd, struct urb *urb)
...
@@ -1805,38 +1806,42 @@ static void uhci_finish_urb(struct usb_hcd *hcd, struct urb *urb)
struct
urb_priv
*
urbp
=
(
struct
urb_priv
*
)
urb
->
hcpriv
;
struct
urb_priv
*
urbp
=
(
struct
urb_priv
*
)
urb
->
hcpriv
;
struct
usb_device
*
dev
=
urb
->
dev
;
struct
usb_device
*
dev
=
urb
->
dev
;
struct
uhci_hcd
*
uhci
=
hcd_to_uhci
(
hcd
);
struct
uhci_hcd
*
uhci
=
hcd_to_uhci
(
hcd
);
int
killed
,
resubmit_interrupt
,
status
;
int
killed
,
resubmit_interrupt
,
status
,
ret
;
unsigned
long
flags
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
urb
->
lock
,
flags
);
spin_lock_irqsave
(
&
urb
->
lock
,
flags
);
killed
=
(
urb
->
status
==
-
ENOENT
||
urb
->
status
==
-
ECONNRESET
);
killed
=
(
urb
->
status
==
-
ENOENT
||
urb
->
status
==
-
ECONNRESET
);
resubmit_interrupt
=
(
usb_pipetype
(
urb
->
pipe
)
==
PIPE_INTERRUPT
&&
resubmit_interrupt
=
(
usb_pipetype
(
urb
->
pipe
)
==
PIPE_INTERRUPT
&&
urb
->
interval
);
urb
->
interval
&&
!
killed
);
status
=
urbp
->
status
;
status
=
urbp
->
status
;
if
(
!
resubmit_interrupt
||
killed
)
/* We don't need urb_priv anymore */
uhci_destroy_urb_priv
(
uhci
,
urb
);
uhci_destroy_urb_priv
(
uhci
,
urb
);
if
(
!
killed
)
if
(
!
killed
)
urb
->
status
=
status
;
urb
->
status
=
status
;
spin_unlock_irqrestore
(
&
urb
->
lock
,
flags
);
spin_unlock_irqrestore
(
&
urb
->
lock
,
flags
);
if
(
resubmit_interrupt
)
if
(
resubmit_interrupt
)
{
urb
->
complete
(
urb
);
urb
->
complete
(
urb
);
else
usb_hcd_giveback_urb
(
hcd
,
urb
);
if
(
resubmit_interrupt
)
/* Recheck the status. The completion handler may have */
/* Recheck the status. The completion handler may have */
/* unlinked the resubmitting interrupt URB */
/* unlinked the resubmitting interrupt URB */
killed
=
(
urb
->
status
==
-
ENOENT
||
urb
->
status
==
-
ECONNRESET
);
/* Note that this doesn't do what usb_hcd_giveback_urb() */
/* normally does, so that doesn't ever get done. */
if
(
urb
->
status
==
-
ECONNRESET
)
{
usb_put_urb
(
urb
);
return
;
}
if
(
resubmit_interrupt
&&
!
killed
)
{
urb
->
dev
=
dev
;
urb
->
dev
=
dev
;
uhci_reset_interrupt
(
uhci
,
urb
);
urb
->
status
=
-
EINPROGRESS
;
}
urb
->
actual_length
=
0
;
urb
->
bandwidth
=
0
;
if
((
ret
=
uhci_urb_enqueue
(
&
uhci
->
hcd
,
urb
,
0
)))
printk
(
KERN_ERR
__FILE__
": could not resubmit interrupt URB : %d
\n
"
,
ret
);
}
else
usb_hcd_giveback_urb
(
hcd
,
urb
);
}
}
static
void
uhci_finish_completion
(
struct
usb_hcd
*
hcd
)
static
void
uhci_finish_completion
(
struct
usb_hcd
*
hcd
)
...
@@ -2041,10 +2046,9 @@ static void release_uhci(struct uhci_hcd *uhci)
...
@@ -2041,10 +2046,9 @@ static void release_uhci(struct uhci_hcd *uhci)
uhci
->
skelqh
[
i
]
=
NULL
;
uhci
->
skelqh
[
i
]
=
NULL
;
}
}
for
(
i
=
0
;
i
<
UHCI_NUM_SKELTD
;
i
++
)
if
(
uhci
->
term_td
)
{
if
(
uhci
->
skeltd
[
i
])
{
uhci_free_td
(
uhci
,
uhci
->
term_td
);
uhci_free_td
(
uhci
,
uhci
->
skeltd
[
i
]);
uhci
->
term_td
=
NULL
;
uhci
->
skeltd
[
i
]
=
NULL
;
}
}
if
(
uhci
->
qh_pool
)
{
if
(
uhci
->
qh_pool
)
{
...
@@ -2193,34 +2197,10 @@ static int __devinit uhci_start(struct usb_hcd *hcd)
...
@@ -2193,34 +2197,10 @@ static int __devinit uhci_start(struct usb_hcd *hcd)
goto
err_alloc_root_hub
;
goto
err_alloc_root_hub
;
}
}
uhci
->
skeltd
[
0
]
=
uhci_alloc_td
(
uhci
,
udev
);
uhci
->
term_td
=
uhci_alloc_td
(
uhci
,
udev
);
if
(
!
uhci
->
skeltd
[
0
])
{
if
(
!
uhci
->
term_td
)
{
err
(
"unable to allocate TD 0"
);
err
(
"unable to allocate terminating TD"
);
goto
err_alloc_skeltd
;
goto
err_alloc_term_td
;
}
/*
* 9 Interrupt queues; link int2 to int1, int4 to int2, etc
* then link int1 to control and control to bulk
*/
for
(
i
=
1
;
i
<
9
;
i
++
)
{
struct
uhci_td
*
td
;
td
=
uhci
->
skeltd
[
i
]
=
uhci_alloc_td
(
uhci
,
udev
);
if
(
!
td
)
{
err
(
"unable to allocate TD %d"
,
i
);
goto
err_alloc_skeltd
;
}
uhci_fill_td
(
td
,
0
,
uhci_explen
(
UHCI_NULL_DATA_SIZE
)
|
(
0x7f
<<
TD_TOKEN_DEVADDR_SHIFT
)
|
USB_PID_IN
,
0
);
td
->
link
=
cpu_to_le32
(
uhci
->
skeltd
[
i
-
1
]
->
dma_handle
);
}
uhci
->
skel_term_td
=
uhci_alloc_td
(
uhci
,
udev
);
if
(
!
uhci
->
skel_term_td
)
{
err
(
"unable to allocate skel TD term"
);
goto
err_alloc_skeltd
;
}
}
for
(
i
=
0
;
i
<
UHCI_NUM_SKELQH
;
i
++
)
{
for
(
i
=
0
;
i
<
UHCI_NUM_SKELQH
;
i
++
)
{
...
@@ -2231,26 +2211,30 @@ static int __devinit uhci_start(struct usb_hcd *hcd)
...
@@ -2231,26 +2211,30 @@ static int __devinit uhci_start(struct usb_hcd *hcd)
}
}
}
}
uhci_fill_td
(
uhci
->
skel_int1_td
,
0
,
(
UHCI_NULL_DATA_SIZE
<<
21
)
|
/*
(
0x7f
<<
TD_TOKEN_DEVADDR_SHIFT
)
|
USB_PID_IN
,
0
);
* 8 Interrupt queues; link int2 to int1, int4 to int2, etc
uhci
->
skel_int1_td
->
link
=
cpu_to_le32
(
uhci
->
skel_ls_control_qh
->
dma_handle
)
|
UHCI_PTR_QH
;
* then link int1 to control and control to bulk
*/
uhci
->
skel_int128_qh
->
link
=
cpu_to_le32
(
uhci
->
skel_int64_qh
->
dma_handle
)
|
UHCI_PTR_QH
;
uhci
->
skel_int64_qh
->
link
=
cpu_to_le32
(
uhci
->
skel_int32_qh
->
dma_handle
)
|
UHCI_PTR_QH
;
uhci
->
skel_int32_qh
->
link
=
cpu_to_le32
(
uhci
->
skel_int16_qh
->
dma_handle
)
|
UHCI_PTR_QH
;
uhci
->
skel_int16_qh
->
link
=
cpu_to_le32
(
uhci
->
skel_int8_qh
->
dma_handle
)
|
UHCI_PTR_QH
;
uhci
->
skel_int8_qh
->
link
=
cpu_to_le32
(
uhci
->
skel_int4_qh
->
dma_handle
)
|
UHCI_PTR_QH
;
uhci
->
skel_int4_qh
->
link
=
cpu_to_le32
(
uhci
->
skel_int2_qh
->
dma_handle
)
|
UHCI_PTR_QH
;
uhci
->
skel_int2_qh
->
link
=
cpu_to_le32
(
uhci
->
skel_int1_qh
->
dma_handle
)
|
UHCI_PTR_QH
;
uhci
->
skel_int1_qh
->
link
=
cpu_to_le32
(
uhci
->
skel_ls_control_qh
->
dma_handle
)
|
UHCI_PTR_QH
;
uhci
->
skel_ls_control_qh
->
link
=
cpu_to_le32
(
uhci
->
skel_hs_control_qh
->
dma_handle
)
|
UHCI_PTR_QH
;
uhci
->
skel_ls_control_qh
->
link
=
cpu_to_le32
(
uhci
->
skel_hs_control_qh
->
dma_handle
)
|
UHCI_PTR_QH
;
uhci
->
skel_ls_control_qh
->
element
=
UHCI_PTR_TERM
;
uhci
->
skel_hs_control_qh
->
link
=
cpu_to_le32
(
uhci
->
skel_bulk_qh
->
dma_handle
)
|
UHCI_PTR_QH
;
uhci
->
skel_hs_control_qh
->
link
=
cpu_to_le32
(
uhci
->
skel_bulk_qh
->
dma_handle
)
|
UHCI_PTR_QH
;
uhci
->
skel_hs_control_qh
->
element
=
UHCI_PTR_TERM
;
uhci
->
skel_bulk_qh
->
link
=
cpu_to_le32
(
uhci
->
skel_term_qh
->
dma_handle
)
|
UHCI_PTR_QH
;
uhci
->
skel_bulk_qh
->
link
=
cpu_to_le32
(
uhci
->
skel_term_qh
->
dma_handle
)
|
UHCI_PTR_QH
;
uhci
->
skel_bulk_qh
->
element
=
UHCI_PTR_TERM
;
/* This dummy TD is to work around a bug in Intel PIIX controllers */
/* This dummy TD is to work around a bug in Intel PIIX controllers */
uhci_fill_td
(
uhci
->
skel_
term_td
,
0
,
(
UHCI_NULL_DATA_SIZE
<<
21
)
|
uhci_fill_td
(
uhci
->
term_td
,
0
,
(
UHCI_NULL_DATA_SIZE
<<
21
)
|
(
0x7f
<<
TD_TOKEN_DEVADDR_SHIFT
)
|
USB_PID_IN
,
0
);
(
0x7f
<<
TD_TOKEN_DEVADDR_SHIFT
)
|
USB_PID_IN
,
0
);
uhci
->
skel_term_td
->
link
=
cpu_to_le32
(
uhci
->
skel_
term_td
->
dma_handle
);
uhci
->
term_td
->
link
=
cpu_to_le32
(
uhci
->
term_td
->
dma_handle
);
uhci
->
skel_term_qh
->
link
=
UHCI_PTR_TERM
;
uhci
->
skel_term_qh
->
link
=
UHCI_PTR_TERM
;
uhci
->
skel_term_qh
->
element
=
cpu_to_le32
(
uhci
->
skel_
term_td
->
dma_handle
);
uhci
->
skel_term_qh
->
element
=
cpu_to_le32
(
uhci
->
term_td
->
dma_handle
);
/*
/*
* Fill the frame list: make all entries point to
* Fill the frame list: make all entries point to
...
@@ -2285,7 +2269,7 @@ static int __devinit uhci_start(struct usb_hcd *hcd)
...
@@ -2285,7 +2269,7 @@ static int __devinit uhci_start(struct usb_hcd *hcd)
}
}
/* Only place we don't use the frame list routines */
/* Only place we don't use the frame list routines */
uhci
->
fl
->
frame
[
i
]
=
cpu_to_le32
(
uhci
->
skel
td
[
irq
]
->
dma_handle
);
uhci
->
fl
->
frame
[
i
]
=
cpu_to_le32
(
uhci
->
skel
qh
[
7
-
irq
]
->
dma_handle
);
}
}
start_hc
(
uhci
);
start_hc
(
uhci
);
...
@@ -2314,20 +2298,17 @@ static int __devinit uhci_start(struct usb_hcd *hcd)
...
@@ -2314,20 +2298,17 @@ static int __devinit uhci_start(struct usb_hcd *hcd)
del_timer_sync
(
&
uhci
->
stall_timer
);
del_timer_sync
(
&
uhci
->
stall_timer
);
err_alloc_skelqh:
for
(
i
=
0
;
i
<
UHCI_NUM_SKELQH
;
i
++
)
for
(
i
=
0
;
i
<
UHCI_NUM_SKELQH
;
i
++
)
if
(
uhci
->
skelqh
[
i
])
{
if
(
uhci
->
skelqh
[
i
])
{
uhci_free_qh
(
uhci
,
uhci
->
skelqh
[
i
]);
uhci_free_qh
(
uhci
,
uhci
->
skelqh
[
i
]);
uhci
->
skelqh
[
i
]
=
NULL
;
uhci
->
skelqh
[
i
]
=
NULL
;
}
}
err_alloc_skelqh:
uhci_free_td
(
uhci
,
uhci
->
term_td
);
for
(
i
=
0
;
i
<
UHCI_NUM_SKELTD
;
i
++
)
uhci
->
term_td
=
NULL
;
if
(
uhci
->
skeltd
[
i
])
{
uhci_free_td
(
uhci
,
uhci
->
skeltd
[
i
]);
uhci
->
skeltd
[
i
]
=
NULL
;
}
err_alloc_
skel
td:
err_alloc_
term_
td:
usb_free_dev
(
udev
);
usb_free_dev
(
udev
);
hcd
->
self
.
root_hub
=
NULL
;
hcd
->
self
.
root_hub
=
NULL
;
...
@@ -2517,7 +2498,7 @@ static int __init uhci_hcd_init(void)
...
@@ -2517,7 +2498,7 @@ static int __init uhci_hcd_init(void)
up_failed:
up_failed:
#ifdef CONFIG_PROC_FS
#ifdef CONFIG_PROC_FS
remove_proc_entry
(
"uhci"
,
0
);
remove_proc_entry
(
"
driver/
uhci"
,
0
);
proc_failed:
proc_failed:
#endif
#endif
...
@@ -2537,7 +2518,7 @@ static void __exit uhci_hcd_cleanup(void)
...
@@ -2537,7 +2518,7 @@ static void __exit uhci_hcd_cleanup(void)
printk
(
KERN_INFO
"uhci: not all urb_priv's were freed
\n
"
);
printk
(
KERN_INFO
"uhci: not all urb_priv's were freed
\n
"
);
#ifdef CONFIG_PROC_FS
#ifdef CONFIG_PROC_FS
remove_proc_entry
(
"uhci"
,
0
);
remove_proc_entry
(
"
driver/
uhci"
,
0
);
#endif
#endif
if
(
errbuf
)
if
(
errbuf
)
...
...
drivers/usb/host/uhci-hcd.h
View file @
2c9fbaf4
...
@@ -81,7 +81,8 @@ struct uhci_frame_list {
...
@@ -81,7 +81,8 @@ struct uhci_frame_list {
struct
urb_priv
;
struct
urb_priv
;
/* One role of a QH is to hold a queue of TDs for some endpoint. Each QH is
/*
* One role of a QH is to hold a queue of TDs for some endpoint. Each QH is
* used with one URB, and qh->element (updated by the HC) is either:
* used with one URB, and qh->element (updated by the HC) is either:
* - the next unprocessed TD for the URB, or
* - the next unprocessed TD for the URB, or
* - UHCI_PTR_TERM (when there's no more traffic for this endpoint), or
* - UHCI_PTR_TERM (when there's no more traffic for this endpoint), or
...
@@ -194,85 +195,63 @@ struct uhci_td {
...
@@ -194,85 +195,63 @@ struct uhci_td {
}
__attribute__
((
aligned
(
16
)));
}
__attribute__
((
aligned
(
16
)));
/*
/*
* There are various standard queues. We set up several different
* The UHCI driver places Interrupt, Control and Bulk into QH's both
* queues for each of the three basic queue types: interrupt,
* to group together TD's for one transfer, and also to faciliate queuing
* control, and bulk.
* of URB's. To make it easy to insert entries into the schedule, we have
*
* a skeleton of QH's for each predefined Interrupt latency, low speed
* - There are various different interrupt latencies: ranging from
* control, high speed control and terminating QH (see explanation for
* every other USB frame (2 ms apart) to every 256 USB frames (ie
* the terminating QH below).
* 256 ms apart). Make your choice according to how obnoxious you
* want to be on the wire, vs how critical latency is for you.
* - The control list is done every frame.
* - There are 4 bulk lists, so that up to four devices can have a
* bulk list of their own and when run concurrently all four lists
* will be be serviced.
*
* This is a bit misleading, there are various interrupt latencies, but they
* vary a bit, interrupt2 isn't exactly 2ms, it can vary up to 4ms since the
* other queues can "override" it. interrupt4 can vary up to 8ms, etc. Minor
* problem
*
* In the case of the root hub, these QH's are just head's of qh's. Don't
* be scared, it kinda makes sense. Look at this wonderful picture care of
* Linus:
*
*
* generic- -> dev1- -> generic- -> dev1- -> control- -> bulk- -> ...
* When we want to add a new QH, we add it to the end of the list for the
* iso-QH iso-QH irq-QH irq-QH QH QH
* skeleton QH.
* | | | | | |
* End dev1-iso-TD1 End dev1-irq-TD1 ... ...
* |
* dev1-iso-TD2
* |
* ....
*
*
* This may vary a bit (the UHCI docs don't explicitly say you can put iso
* For instance, the queue can look like this:
* transfers in QH's and all of their pictures don't have that either) but
* other than that, that is what we're doing now
*
*
* And now we don't put Iso transfers in QH's, so we don't waste one on it
* skel int128 QH
* --jerdfelt
* dev 1 interrupt QH
* dev 5 interrupt QH
* skel int64 QH
* skel int32 QH
* ...
* skel int1 QH
* skel low speed control QH
* dev 5 control QH
* skel high speed control QH
* skel bulk QH
* dev 1 bulk QH
* dev 2 bulk QH
* skel terminating QH
*
*
* To keep with Linus' nomenclature, this is called the QH skeleton. These
* The terminating QH is used for 2 reasons:
* labels (below) are only signficant to the root hub's QH's
* - To place a terminating TD which is used to workaround a PIIX bug
* (see Intel errata for explanation)
* - To loop back to the high speed control queue for full speed bandwidth
* reclamation
*
*
*
* Isochronous transfers are stored before the start of the skeleton
* NOTE: That ASCII art doesn't match the current (August 2002) code, in
* schedule and don't use QH's. While the UHCI spec doesn't forbid the
* more ways than just not using QHs for ISO.
* use of QH's for Isochronous, it doesn't use them either. Since we don't
*
* need to use them either, we follow the spec diagrams in hope that it'll
* NOTE: Another way to look at the UHCI schedules is to compare them to what
* be more compatible with future UHCI implementations.
* other host controller interfaces use. EHCI, OHCI, and UHCI all have tables
* of transfers that the controller scans, frame by frame, and which hold the
* scheduled periodic transfers. The key differences are that UHCI
*
* (a) puts control and bulk transfers into that same table; the others
* have separate data structures for non-periodic transfers.
* (b) lets QHs be linked from TDs, not just other QHs, since they don't
* hold endpoint data. this driver chooses to use one QH per URB.
* (c) needs more TDs, since it uses one per packet. the data toggle
* is stored in those TDs, along with all other endpoint state.
*/
*/
#define UHCI_NUM_SKELTD 10
#define UHCI_NUM_SKELQH 12
#define skel_int1_td skeltd[0]
#define skel_int128_qh skelqh[0]
#define skel_int2_td skeltd[1]
#define skel_int64_qh skelqh[1]
#define skel_int4_td skeltd[2]
#define skel_int32_qh skelqh[2]
#define skel_int8_td skeltd[3]
#define skel_int16_qh skelqh[3]
#define skel_int16_td skeltd[4]
#define skel_int8_qh skelqh[4]
#define skel_int32_td skeltd[5]
#define skel_int4_qh skelqh[5]
#define skel_int64_td skeltd[6]
#define skel_int2_qh skelqh[6]
#define skel_int128_td skeltd[7]
#define skel_int1_qh skelqh[7]
#define skel_int256_td skeltd[8]
#define skel_ls_control_qh skelqh[8]
#define skel_term_td skeltd[9]
/* To work around PIIX UHCI bug */
#define skel_hs_control_qh skelqh[9]
#define skel_bulk_qh skelqh[10]
#define UHCI_NUM_SKELQH 4
#define skel_term_qh skelqh[11]
#define skel_ls_control_qh skelqh[0]
#define skel_hs_control_qh skelqh[1]
#define skel_bulk_qh skelqh[2]
#define skel_term_qh skelqh[3]
/*
/*
* Search tree for determining where <interval> fits in the
* Search tree for determining where <interval> fits in the
skelqh[]
* skel
qh[] skel
eton.
* skeleton.
*
*
* An interrupt request should be placed into the slowest skelqh[]
* An interrupt request should be placed into the slowest skelqh[]
* which meets the interval/period/frequency requirement.
* which meets the interval/period/frequency requirement.
...
@@ -280,32 +259,27 @@ struct uhci_td {
...
@@ -280,32 +259,27 @@ struct uhci_td {
*
*
* For a given <interval>, this function returns the appropriate/matching
* For a given <interval>, this function returns the appropriate/matching
* skelqh[] index value.
* skelqh[] index value.
*
* NOTE: For UHCI, we don't really need int256_qh since the maximum interval
* is 255 ms. However, we do need an int1_qh since 1 is a valid interval
* and we should meet that frequency when requested to do so.
* This will require some change(s) to the UHCI skeleton.
*/
*/
static
inline
int
__interval_to_skel
(
int
interval
)
static
inline
int
__interval_to_skel
(
int
interval
)
{
{
if
(
interval
<
16
)
{
if
(
interval
<
16
)
{
if
(
interval
<
4
)
{
if
(
interval
<
4
)
{
if
(
interval
<
2
)
if
(
interval
<
2
)
return
0
;
/* int1 for 0-1 ms */
return
7
;
/* int1 for 0-1 ms */
return
1
;
/* int2 for 2-3 ms */
return
6
;
/* int2 for 2-3 ms */
}
}
if
(
interval
<
8
)
if
(
interval
<
8
)
return
2
;
/* int4 for 4-7 ms */
return
5
;
/* int4 for 4-7 ms */
return
3
;
/* int8 for 8-15 ms */
return
4
;
/* int8 for 8-15 ms */
}
}
if
(
interval
<
64
)
{
if
(
interval
<
64
)
{
if
(
interval
<
32
)
if
(
interval
<
32
)
return
4
;
/* int16 for 16-31 ms */
return
3
;
/* int16 for 16-31 ms */
return
5
;
/* int32 for 32-63 ms */
return
2
;
/* int32 for 32-63 ms */
}
}
if
(
interval
<
128
)
if
(
interval
<
128
)
return
6
;
/* int64 for 64-127 ms */
return
1
;
/* int64 for 64-127 ms */
return
7
;
/* int128 for 128-255 ms (Max.) */
return
0
;
/* int128 for 128-255 ms (Max.) */
}
}
#define hcd_to_uhci(hcd_ptr) container_of(hcd_ptr, struct uhci_hcd, hcd)
#define hcd_to_uhci(hcd_ptr) container_of(hcd_ptr, struct uhci_hcd, hcd)
...
@@ -332,7 +306,7 @@ struct uhci_hcd {
...
@@ -332,7 +306,7 @@ struct uhci_hcd {
struct
usb_bus
*
bus
;
struct
usb_bus
*
bus
;
struct
uhci_td
*
skeltd
[
UHCI_NUM_SKELTD
];
/* Skeleton TD's
*/
struct
uhci_td
*
term_td
;
/* Terminating TD, see UHCI bug
*/
struct
uhci_qh
*
skelqh
[
UHCI_NUM_SKELQH
];
/* Skeleton QH's */
struct
uhci_qh
*
skelqh
[
UHCI_NUM_SKELQH
];
/* Skeleton QH's */
spinlock_t
frame_list_lock
;
spinlock_t
frame_list_lock
;
...
...
drivers/usb/input/Config.help
View file @
2c9fbaf4
...
@@ -63,7 +63,8 @@ CONFIG_USB_KBD
...
@@ -63,7 +63,8 @@ CONFIG_USB_KBD
to use the generic HID driver for your USB keyboard and prefer
to use the generic HID driver for your USB keyboard and prefer
to use the keyboard in its limited Boot Protocol mode instead.
to use the keyboard in its limited Boot Protocol mode instead.
This is almost certainly not what you want.
This is almost certainly not what you want. This is mostly
useful for embedded applications or simple keyboards.
This code is also available as a module ( = code which can be
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
inserted in and removed from the running kernel whenever you want).
...
@@ -77,7 +78,8 @@ CONFIG_USB_MOUSE
...
@@ -77,7 +78,8 @@ CONFIG_USB_MOUSE
to use the generic HID driver for your USB keyboard and prefer
to use the generic HID driver for your USB keyboard and prefer
to use the keyboard in its limited Boot Protocol mode instead.
to use the keyboard in its limited Boot Protocol mode instead.
This is almost certainly not what you want.
This is almost certainly not what you want. This is mostly
useful for embedded applications or simple mice.
This code is also available as a module ( = code which can be
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
inserted in and removed from the running kernel whenever you want).
...
...
drivers/usb/input/Config.in
View file @
2c9fbaf4
...
@@ -15,8 +15,11 @@ dep_mbool ' Logitech WingMan *3D support' CONFIG_LOGITECH_FF $CONFIG_USB_
...
@@ -15,8 +15,11 @@ dep_mbool ' Logitech WingMan *3D support' CONFIG_LOGITECH_FF $CONFIG_USB_
dep_mbool ' /dev/hiddev raw HID device support' CONFIG_USB_HIDDEV $CONFIG_USB_HID
dep_mbool ' /dev/hiddev raw HID device support' CONFIG_USB_HIDDEV $CONFIG_USB_HID
if [ "$CONFIG_USB_HID" != "y" ]; then
if [ "$CONFIG_USB_HID" != "y" ]; then
dep_tristate ' USB HIDBP Keyboard (basic) support' CONFIG_USB_KBD $CONFIG_USB $CONFIG_INPUT
mainmenu_option next_comment
dep_tristate ' USB HIDBP Mouse (basic) support' CONFIG_USB_MOUSE $CONFIG_USB $CONFIG_INPUT
comment 'USB HID Boot Protocol drivers'
dep_tristate ' USB HIDBP Keyboard (simple Boot) support' CONFIG_USB_KBD $CONFIG_USB $CONFIG_INPUT
dep_tristate ' USB HIDBP Mouse (simple Boot) support' CONFIG_USB_MOUSE $CONFIG_USB $CONFIG_INPUT
endmenu
fi
fi
dep_tristate ' Aiptek 6000U/8000U tablet support' CONFIG_USB_AIPTEK $CONFIG_USB $CONFIG_INPUT
dep_tristate ' Aiptek 6000U/8000U tablet support' CONFIG_USB_AIPTEK $CONFIG_USB $CONFIG_INPUT
...
...
drivers/usb/misc/usbtest.c
View file @
2c9fbaf4
...
@@ -109,7 +109,7 @@ static struct urb *simple_alloc_urb (
...
@@ -109,7 +109,7 @@ static struct urb *simple_alloc_urb (
usb_fill_bulk_urb
(
urb
,
udev
,
pipe
,
0
,
bytes
,
simple_callback
,
0
);
usb_fill_bulk_urb
(
urb
,
udev
,
pipe
,
0
,
bytes
,
simple_callback
,
0
);
urb
->
interval
=
(
udev
->
speed
==
USB_SPEED_HIGH
)
urb
->
interval
=
(
udev
->
speed
==
USB_SPEED_HIGH
)
?
(
INTERRUPT_RATE
<<
3
)
?
(
INTERRUPT_RATE
<<
3
)
:
INTERRUPT_RATE
,
:
INTERRUPT_RATE
;
urb
->
transfer_flags
=
URB_NO_DMA_MAP
;
urb
->
transfer_flags
=
URB_NO_DMA_MAP
;
if
(
usb_pipein
(
pipe
))
if
(
usb_pipein
(
pipe
))
urb
->
transfer_flags
|=
URB_SHORT_NOT_OK
;
urb
->
transfer_flags
|=
URB_SHORT_NOT_OK
;
...
@@ -142,7 +142,7 @@ static int simple_io (
...
@@ -142,7 +142,7 @@ static int simple_io (
int
retval
=
0
;
int
retval
=
0
;
urb
->
context
=
&
completion
;
urb
->
context
=
&
completion
;
while
(
iterations
--
>
0
&&
retval
==
0
)
{
while
(
retval
==
0
&&
iterations
--
>
0
)
{
init_completion
(
&
completion
);
init_completion
(
&
completion
);
if
((
retval
=
usb_submit_urb
(
urb
,
SLAB_KERNEL
))
!=
0
)
if
((
retval
=
usb_submit_urb
(
urb
,
SLAB_KERNEL
))
!=
0
)
break
;
break
;
...
@@ -155,7 +155,7 @@ static int simple_io (
...
@@ -155,7 +155,7 @@ static int simple_io (
if
(
vary
)
{
if
(
vary
)
{
int
len
=
urb
->
transfer_buffer_length
;
int
len
=
urb
->
transfer_buffer_length
;
len
+=
max
;
len
+=
vary
;
len
%=
max
;
len
%=
max
;
if
(
len
==
0
)
if
(
len
==
0
)
len
=
(
vary
<
max
)
?
vary
:
max
;
len
=
(
vary
<
max
)
?
vary
:
max
;
...
@@ -347,7 +347,7 @@ static int set_altsetting (struct usbtest_dev *dev, int alternate)
...
@@ -347,7 +347,7 @@ static int set_altsetting (struct usbtest_dev *dev, int alternate)
ep
&=
USB_ENDPOINT_NUMBER_MASK
;
ep
&=
USB_ENDPOINT_NUMBER_MASK
;
usb_settoggle
(
udev
,
ep
,
out
,
0
);
usb_settoggle
(
udev
,
ep
,
out
,
0
);
(
out
?
udev
->
epmaxpacketout
:
udev
->
epmaxpacketin
)
[
ep
]
(
out
?
udev
->
epmaxpacketout
:
udev
->
epmaxpacketin
)
[
ep
]
=
iface_as
->
endpoint
[
ep
].
wMaxPacketSize
;
=
iface_as
->
endpoint
[
i
].
wMaxPacketSize
;
}
}
return
0
;
return
0
;
...
@@ -659,7 +659,7 @@ static int usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *b
...
@@ -659,7 +659,7 @@ static int usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *b
break
;
break
;
dbg
(
"%s TEST 4: read/%d 0..%d bytes %u times"
,
dev
->
id
,
dbg
(
"%s TEST 4: read/%d 0..%d bytes %u times"
,
dev
->
id
,
param
->
vary
,
param
->
length
,
param
->
iterations
);
param
->
vary
,
param
->
length
,
param
->
iterations
);
urb
=
simple_alloc_urb
(
udev
,
dev
->
out
_pipe
,
param
->
length
);
urb
=
simple_alloc_urb
(
udev
,
dev
->
in
_pipe
,
param
->
length
);
if
(
!
urb
)
{
if
(
!
urb
)
{
retval
=
-
ENOMEM
;
retval
=
-
ENOMEM
;
break
;
break
;
...
@@ -907,6 +907,14 @@ static struct usbtest_info ez2_info = {
...
@@ -907,6 +907,14 @@ static struct usbtest_info ez2_info = {
.
alt
=
1
,
.
alt
=
1
,
};
};
/* ezusb family device with dedicated usb test firmware*/
static
struct
usbtest_info
fw_info
=
{
.
name
=
"usb test device"
,
.
ep_in
=
2
,
.
ep_out
=
2
,
.
alt
=
0
,
};
#ifdef IBOT2
#ifdef IBOT2
/* this is a nice source of high speed bulk data;
/* this is a nice source of high speed bulk data;
* uses an FX2, with firmware provided in the device
* uses an FX2, with firmware provided in the device
...
@@ -962,6 +970,11 @@ static struct usb_device_id id_table [] = {
...
@@ -962,6 +970,11 @@ static struct usb_device_id id_table [] = {
.
driver_info
=
(
unsigned
long
)
&
ez2_info
,
.
driver_info
=
(
unsigned
long
)
&
ez2_info
,
},
},
/* re-enumerated usb test device firmware */
{
USB_DEVICE
(
0xfff0
,
0xfff0
),
.
driver_info
=
(
unsigned
long
)
&
fw_info
,
},
#ifdef KEYSPAN_19Qi
#ifdef KEYSPAN_19Qi
/* Keyspan 19qi uses an21xx (original EZ-USB) */
/* Keyspan 19qi uses an21xx (original EZ-USB) */
// this does not coexist with the real Keyspan 19qi driver!
// this does not coexist with the real Keyspan 19qi driver!
...
...
drivers/usb/net/pegasus.h
View file @
2c9fbaf4
...
@@ -135,6 +135,7 @@ struct usb_eth_dev {
...
@@ -135,6 +135,7 @@ struct usb_eth_dev {
#define VENDOR_SMC 0x0707
#define VENDOR_SMC 0x0707
#define VENDOR_SOHOWARE 0x15e8
#define VENDOR_SOHOWARE 0x15e8
#define VENDOR_SIEMENS 0x067c
#define VENDOR_SIEMENS 0x067c
#define VENDOR_JTEC 0x11ad
#else
/* PEGASUS_DEV */
#else
/* PEGASUS_DEV */
...
@@ -257,6 +258,8 @@ PEGASUS_DEV( "SOHOware NUB110 Ethernet", VENDOR_SOHOWARE, 0x9110,
...
@@ -257,6 +258,8 @@ PEGASUS_DEV( "SOHOware NUB110 Ethernet", VENDOR_SOHOWARE, 0x9110,
DEFAULT_GPIO_RESET
|
PEGASUS_II
)
DEFAULT_GPIO_RESET
|
PEGASUS_II
)
PEGASUS_DEV
(
"SpeedStream USB 10/100 Ethernet"
,
VENDOR_SIEMENS
,
0x1001
,
PEGASUS_DEV
(
"SpeedStream USB 10/100 Ethernet"
,
VENDOR_SIEMENS
,
0x1001
,
DEFAULT_GPIO_RESET
|
PEGASUS_II
)
DEFAULT_GPIO_RESET
|
PEGASUS_II
)
PEGASUS_DEV
(
"FA8101 USB To ETHERNET"
,
VENDOR_JTEC
,
0x8101
,
DEFAULT_GPIO_RESET
|
PEGASUS_II
)
#endif
/* PEGASUS_DEV */
#endif
/* PEGASUS_DEV */
drivers/usb/storage/transport.c
View file @
2c9fbaf4
...
@@ -647,6 +647,7 @@ int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe,
...
@@ -647,6 +647,7 @@ int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe,
/* no error code, so we must have transferred some data,
/* no error code, so we must have transferred some data,
* just not all of it */
* just not all of it */
US_DEBUGP
(
"-- transferred only %d bytes
\n
"
,
partial
);
return
USB_STOR_XFER_SHORT
;
return
USB_STOR_XFER_SHORT
;
}
}
...
@@ -654,15 +655,15 @@ int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe,
...
@@ -654,15 +655,15 @@ int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe,
* Transfer an entire SCSI command's worth of data payload over the bulk
* Transfer an entire SCSI command's worth of data payload over the bulk
* pipe.
* pipe.
*
*
* Note that this uses usb_stor_
transfer_buf to achieve its goals -- this
* Note that this uses usb_stor_
bulk_transfer_buf to achieve its goals --
* function simply determines if we're going to use scatter-gather or not,
*
this
function simply determines if we're going to use scatter-gather or not,
* and acts appropriately.
For now, it also re-interprets the error codes.
* and acts appropriately.
*/
*/
int
usb_stor_bulk_transfer_sg
(
struct
us_data
*
us
,
unsigned
int
pipe
,
int
usb_stor_bulk_transfer_sg
(
struct
us_data
*
us
,
unsigned
int
pipe
,
char
*
buf
,
unsigned
int
length_left
,
int
use_sg
,
int
*
residual
)
char
*
buf
,
unsigned
int
length_left
,
int
use_sg
,
int
*
residual
)
{
{
int
i
;
int
i
;
int
result
=
-
1
;
int
result
=
USB_STOR_XFER_ERROR
;
struct
scatterlist
*
sg
;
struct
scatterlist
*
sg
;
unsigned
int
amount
;
unsigned
int
amount
;
unsigned
int
partial
;
unsigned
int
partial
;
...
@@ -1046,9 +1047,11 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
...
@@ -1046,9 +1047,11 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
/* DATA STAGE */
/* DATA STAGE */
/* transfer the data payload for this command, if one exists*/
/* transfer the data payload for this command, if one exists*/
if
(
transfer_length
>
0
)
{
if
(
transfer_length
)
{
result
=
usb_stor_bulk_transfer_srb
(
us
,
us
->
send_bulk_pipe
,
unsigned
int
pipe
=
srb
->
sc_data_direction
==
SCSI_DATA_READ
?
srb
,
transfer_length
);
us
->
recv_bulk_pipe
:
us
->
send_bulk_pipe
;
result
=
usb_stor_bulk_transfer_srb
(
us
,
pipe
,
srb
,
transfer_length
);
US_DEBUGP
(
"CBI data stage result is 0x%x
\n
"
,
result
);
US_DEBUGP
(
"CBI data stage result is 0x%x
\n
"
,
result
);
/* report any errors */
/* report any errors */
...
@@ -1140,6 +1143,7 @@ int usb_stor_CB_transport(Scsi_Cmnd *srb, struct us_data *us)
...
@@ -1140,6 +1143,7 @@ int usb_stor_CB_transport(Scsi_Cmnd *srb, struct us_data *us)
if
(
atomic_read
(
&
us
->
sm_state
)
==
US_STATE_ABORTING
)
{
if
(
atomic_read
(
&
us
->
sm_state
)
==
US_STATE_ABORTING
)
{
US_DEBUGP
(
"usb_stor_CB_transport(): transfer aborted
\n
"
);
US_DEBUGP
(
"usb_stor_CB_transport(): transfer aborted
\n
"
);
return
USB_STOR_TRANSPORT_ABORTED
;
return
USB_STOR_TRANSPORT_ABORTED
;
}
if
(
result
!=
USB_STOR_XFER_GOOD
)
{
if
(
result
!=
USB_STOR_XFER_GOOD
)
{
/* Uh oh... serious problem here */
/* Uh oh... serious problem here */
...
@@ -1148,9 +1152,11 @@ int usb_stor_CB_transport(Scsi_Cmnd *srb, struct us_data *us)
...
@@ -1148,9 +1152,11 @@ int usb_stor_CB_transport(Scsi_Cmnd *srb, struct us_data *us)
/* DATA STAGE */
/* DATA STAGE */
/* transfer the data payload for this command, if one exists*/
/* transfer the data payload for this command, if one exists*/
if
(
transfer_length
)
if
(
transfer_length
)
{
result
=
usb_stor_bulk_transfer_srb
(
us
,
us
->
send_bulk_pipe
,
unsigned
int
pipe
=
srb
->
sc_data_direction
==
SCSI_DATA_READ
?
srb
,
transfer_length
);
us
->
recv_bulk_pipe
:
us
->
send_bulk_pipe
;
result
=
usb_stor_bulk_transfer_srb
(
us
,
pipe
,
srb
,
transfer_length
);
US_DEBUGP
(
"CB data stage result is 0x%x
\n
"
,
result
);
US_DEBUGP
(
"CB data stage result is 0x%x
\n
"
,
result
);
/* report any errors */
/* report any errors */
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment