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
nexedi
linux
Commits
cdb7bc8f
Commit
cdb7bc8f
authored
Feb 19, 2004
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge
bk://kernel.bkbits.net/gregkh/linux/usb-2.6
into ppc970.osdl.org:/home/torvalds/v2.5/linux
parents
0f8b375f
d27099da
Changes
33
Show whitespace changes
Inline
Side-by-side
Showing
33 changed files
with
1075 additions
and
750 deletions
+1075
-750
drivers/usb/class/usblp.c
drivers/usb/class/usblp.c
+8
-12
drivers/usb/core/buffer.c
drivers/usb/core/buffer.c
+14
-9
drivers/usb/core/hcd-pci.c
drivers/usb/core/hcd-pci.c
+16
-15
drivers/usb/core/hcd.c
drivers/usb/core/hcd.c
+20
-18
drivers/usb/core/hcd.h
drivers/usb/core/hcd.h
+2
-5
drivers/usb/core/hub.c
drivers/usb/core/hub.c
+7
-2
drivers/usb/core/message.c
drivers/usb/core/message.c
+16
-10
drivers/usb/core/usb.c
drivers/usb/core/usb.c
+10
-3
drivers/usb/host/ehci-dbg.c
drivers/usb/host/ehci-dbg.c
+6
-6
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-hcd.c
+10
-8
drivers/usb/host/ehci-hub.c
drivers/usb/host/ehci-hub.c
+1
-1
drivers/usb/host/ehci-mem.c
drivers/usb/host/ehci-mem.c
+22
-18
drivers/usb/host/ehci-q.c
drivers/usb/host/ehci-q.c
+1
-1
drivers/usb/host/ehci-sched.c
drivers/usb/host/ehci-sched.c
+388
-194
drivers/usb/host/ehci.h
drivers/usb/host/ehci.h
+50
-30
drivers/usb/host/ohci-hcd.c
drivers/usb/host/ohci-hcd.c
+6
-2
drivers/usb/host/ohci-mem.c
drivers/usb/host/ohci-mem.c
+10
-10
drivers/usb/host/ohci-omap.c
drivers/usb/host/ohci-omap.c
+4
-8
drivers/usb/host/ohci-pci.c
drivers/usb/host/ohci-pci.c
+24
-21
drivers/usb/host/ohci-q.c
drivers/usb/host/ohci-q.c
+2
-2
drivers/usb/host/ohci-sa1111.c
drivers/usb/host/ohci-sa1111.c
+6
-10
drivers/usb/host/ohci.h
drivers/usb/host/ohci.h
+6
-6
drivers/usb/host/uhci-debug.c
drivers/usb/host/uhci-debug.c
+19
-16
drivers/usb/host/uhci-hcd.c
drivers/usb/host/uhci-hcd.c
+164
-190
drivers/usb/host/uhci-hcd.h
drivers/usb/host/uhci-hcd.h
+17
-13
drivers/usb/host/uhci-hub.c
drivers/usb/host/uhci-hub.c
+83
-56
drivers/usb/media/stv680.c
drivers/usb/media/stv680.c
+6
-10
drivers/usb/misc/usbtest.c
drivers/usb/misc/usbtest.c
+18
-1
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio.c
+12
-1
drivers/usb/serial/ftdi_sio.h
drivers/usb/serial/ftdi_sio.h
+4
-0
drivers/usb/storage/sddr09.c
drivers/usb/storage/sddr09.c
+30
-1
drivers/usb/storage/transport.c
drivers/usb/storage/transport.c
+41
-37
drivers/usb/storage/unusual_devs.h
drivers/usb/storage/unusual_devs.h
+52
-34
No files found.
drivers/usb/class/usblp.c
View file @
cdb7bc8f
...
...
@@ -603,7 +603,7 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t
{
DECLARE_WAITQUEUE
(
wait
,
current
);
struct
usblp
*
usblp
=
file
->
private_data
;
int
timeout
,
err
=
0
;
int
timeout
,
err
=
0
,
transfer_length
;
size_t
writecount
=
0
;
while
(
writecount
<
count
)
{
...
...
@@ -654,19 +654,13 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t
continue
;
}
writecount
+=
usblp
->
writeurb
->
transfer_buffer_length
;
usblp
->
writeurb
->
transfer_buffer_length
=
0
;
if
(
writecount
==
count
)
{
up
(
&
usblp
->
sem
);
break
;
}
transfer_length
=
(
count
-
writecount
);
if
(
transfer_length
>
USBLP_BUF_SIZE
)
transfer_length
=
USBLP_BUF_SIZE
;
usblp
->
writeurb
->
transfer_buffer_length
=
(
count
-
writecount
)
<
USBLP_BUF_SIZE
?
(
count
-
writecount
)
:
USBLP_BUF_SIZE
;
usblp
->
writeurb
->
transfer_buffer_length
=
transfer_length
;
if
(
copy_from_user
(
usblp
->
writeurb
->
transfer_buffer
,
buffer
+
writecount
,
usblp
->
writeurb
->
transfer_buffer_length
))
{
if
(
copy_from_user
(
usblp
->
writeurb
->
transfer_buffer
,
buffer
+
writecount
,
transfer_length
))
{
up
(
&
usblp
->
sem
);
return
writecount
?
writecount
:
-
EFAULT
;
}
...
...
@@ -683,6 +677,8 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t
break
;
}
up
(
&
usblp
->
sem
);
writecount
+=
transfer_length
;
}
return
count
;
...
...
drivers/usb/core/buffer.c
View file @
cdb7bc8f
...
...
@@ -2,14 +2,19 @@
* DMA memory management for framework level HCD code (hc_driver)
*
* This implementation plugs in through generic "usb_bus" level methods,
* and
works with real PCI, or when "pci device == null" makes sens
e.
* and
should work with all USB controllers, regardles of bus typ
e.
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/pci.h>
#include <linux/device.h>
#include <linux/mm.h>
#include <asm/io.h>
#include <asm/scatterlist.h>
#include <linux/dma-mapping.h>
#include <linux/dmapool.h>
#ifdef CONFIG_USB_DEBUG
...
...
@@ -62,7 +67,7 @@ int hcd_buffer_create (struct usb_hcd *hcd)
if
(
!
(
size
=
pool_max
[
i
]))
continue
;
snprintf
(
name
,
sizeof
name
,
"buffer-%d"
,
size
);
hcd
->
pool
[
i
]
=
pci_pool_create
(
name
,
hcd
->
pdev
,
hcd
->
pool
[
i
]
=
dma_pool_create
(
name
,
hcd
->
self
.
controller
,
size
,
size
,
0
);
if
(
!
hcd
->
pool
[
i
])
{
hcd_buffer_destroy
(
hcd
);
...
...
@@ -86,9 +91,9 @@ void hcd_buffer_destroy (struct usb_hcd *hcd)
int
i
;
for
(
i
=
0
;
i
<
HCD_BUFFER_POOLS
;
i
++
)
{
struct
pci
_pool
*
pool
=
hcd
->
pool
[
i
];
struct
dma
_pool
*
pool
=
hcd
->
pool
[
i
];
if
(
pool
)
{
pci
_pool_destroy
(
pool
);
dma
_pool_destroy
(
pool
);
hcd
->
pool
[
i
]
=
0
;
}
}
...
...
@@ -112,9 +117,9 @@ void *hcd_buffer_alloc (
for
(
i
=
0
;
i
<
HCD_BUFFER_POOLS
;
i
++
)
{
if
(
size
<=
pool_max
[
i
])
return
pci
_pool_alloc
(
hcd
->
pool
[
i
],
mem_flags
,
dma
);
return
dma
_pool_alloc
(
hcd
->
pool
[
i
],
mem_flags
,
dma
);
}
return
pci_alloc_consistent
(
hcd
->
pdev
,
size
,
dma
);
return
dma_alloc_coherent
(
hcd
->
self
.
controller
,
size
,
dma
,
0
);
}
void
hcd_buffer_free
(
...
...
@@ -131,9 +136,9 @@ void hcd_buffer_free (
return
;
for
(
i
=
0
;
i
<
HCD_BUFFER_POOLS
;
i
++
)
{
if
(
size
<=
pool_max
[
i
])
{
pci
_pool_free
(
hcd
->
pool
[
i
],
addr
,
dma
);
dma
_pool_free
(
hcd
->
pool
[
i
],
addr
,
dma
);
return
;
}
}
pci_free_consistent
(
hcd
->
pdev
,
size
,
addr
,
dma
);
dma_free_coherent
(
hcd
->
self
.
controller
,
size
,
addr
,
dma
);
}
drivers/usb/core/hcd-pci.c
View file @
cdb7bc8f
...
...
@@ -146,12 +146,10 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
pci_set_drvdata
(
dev
,
hcd
);
hcd
->
driver
=
driver
;
hcd
->
description
=
driver
->
description
;
hcd
->
pdev
=
dev
;
hcd
->
self
.
bus_name
=
pci_name
(
dev
);
if
(
hcd
->
product_desc
==
NULL
)
hcd
->
product_desc
=
"USB Host Controller"
;
hcd
->
self
.
controller
=
&
dev
->
dev
;
hcd
->
controller
=
hcd
->
self
.
controller
;
if
((
retval
=
hcd_buffer_create
(
hcd
))
!=
0
)
{
clean_3:
...
...
@@ -159,11 +157,11 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
goto
clean_2
;
}
dev_info
(
hcd
->
controller
,
"%s
\n
"
,
hcd
->
product_desc
);
dev_info
(
hcd
->
self
.
controller
,
"%s
\n
"
,
hcd
->
product_desc
);
/* till now HC has been in an indeterminate state ... */
if
(
driver
->
reset
&&
(
retval
=
driver
->
reset
(
hcd
))
<
0
)
{
dev_err
(
hcd
->
controller
,
"can't reset
\n
"
);
dev_err
(
hcd
->
self
.
controller
,
"can't reset
\n
"
);
goto
clean_3
;
}
hcd
->
state
=
USB_STATE_HALT
;
...
...
@@ -177,13 +175,13 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
retval
=
request_irq
(
dev
->
irq
,
usb_hcd_irq
,
SA_SHIRQ
,
hcd
->
description
,
hcd
);
if
(
retval
!=
0
)
{
dev_err
(
hcd
->
controller
,
dev_err
(
hcd
->
self
.
controller
,
"request interrupt %s failed
\n
"
,
bufp
);
goto
clean_3
;
}
hcd
->
irq
=
dev
->
irq
;
dev_info
(
hcd
->
controller
,
"irq %s, %s %p
\n
"
,
bufp
,
dev_info
(
hcd
->
self
.
controller
,
"irq %s, %s %p
\n
"
,
bufp
,
(
driver
->
flags
&
HCD_MEMORY
)
?
"pci mem"
:
"io base"
,
base
);
...
...
@@ -226,7 +224,7 @@ void usb_hcd_pci_remove (struct pci_dev *dev)
hcd
=
pci_get_drvdata
(
dev
);
if
(
!
hcd
)
return
;
dev_info
(
hcd
->
controller
,
"remove, state %x
\n
"
,
hcd
->
state
);
dev_info
(
hcd
->
self
.
controller
,
"remove, state %x
\n
"
,
hcd
->
state
);
if
(
in_interrupt
())
BUG
();
...
...
@@ -235,7 +233,7 @@ void usb_hcd_pci_remove (struct pci_dev *dev)
if
(
HCD_IS_RUNNING
(
hcd
->
state
))
hcd
->
state
=
USB_STATE_QUIESCING
;
dev_dbg
(
hcd
->
controller
,
"roothub graceful disconnect
\n
"
);
dev_dbg
(
hcd
->
self
.
controller
,
"roothub graceful disconnect
\n
"
);
usb_disconnect
(
&
hub
);
hcd
->
driver
->
stop
(
hcd
);
...
...
@@ -273,15 +271,15 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, u32 state)
int
retval
=
0
;
hcd
=
pci_get_drvdata
(
dev
);
dev_dbg
(
hcd
->
controller
,
"suspend D%d --> D%d
\n
"
,
dev_dbg
(
hcd
->
self
.
controller
,
"suspend D%d --> D%d
\n
"
,
dev
->
current_state
,
state
);
switch
(
hcd
->
state
)
{
case
USB_STATE_HALT
:
dev_dbg
(
hcd
->
controller
,
"halted; hcd not suspended
\n
"
);
dev_dbg
(
hcd
->
self
.
controller
,
"halted; hcd not suspended
\n
"
);
break
;
case
USB_STATE_SUSPENDED
:
dev_dbg
(
hcd
->
controller
,
"hcd already suspended
\n
"
);
dev_dbg
(
hcd
->
self
.
controller
,
"hcd already suspended
\n
"
);
break
;
default:
/* remote wakeup needs hub->suspend() cooperation */
...
...
@@ -293,7 +291,8 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, u32 state)
hcd
->
state
=
USB_STATE_QUIESCING
;
retval
=
hcd
->
driver
->
suspend
(
hcd
,
state
);
if
(
retval
)
dev_dbg
(
hcd
->
controller
,
"suspend fail, retval %d
\n
"
,
dev_dbg
(
hcd
->
self
.
controller
,
"suspend fail, retval %d
\n
"
,
retval
);
else
hcd
->
state
=
USB_STATE_SUSPENDED
;
...
...
@@ -316,11 +315,12 @@ int usb_hcd_pci_resume (struct pci_dev *dev)
int
retval
;
hcd
=
pci_get_drvdata
(
dev
);
dev_dbg
(
hcd
->
controller
,
"resume from state D%d
\n
"
,
dev_dbg
(
hcd
->
self
.
controller
,
"resume from state D%d
\n
"
,
dev
->
current_state
);
if
(
hcd
->
state
!=
USB_STATE_SUSPENDED
)
{
dev_dbg
(
hcd
->
controller
,
"can't resume, not suspended!
\n
"
);
dev_dbg
(
hcd
->
self
.
controller
,
"can't resume, not suspended!
\n
"
);
return
-
EL3HLT
;
}
hcd
->
state
=
USB_STATE_RESUMING
;
...
...
@@ -333,7 +333,8 @@ int usb_hcd_pci_resume (struct pci_dev *dev)
retval
=
hcd
->
driver
->
resume
(
hcd
);
if
(
!
HCD_IS_RUNNING
(
hcd
->
state
))
{
dev_dbg
(
hcd
->
controller
,
"resume fail, retval %d
\n
"
,
retval
);
dev_dbg
(
hcd
->
self
.
controller
,
"resume fail, retval %d
\n
"
,
retval
);
usb_hc_died
(
hcd
);
}
...
...
drivers/usb/core/hcd.c
View file @
cdb7bc8f
...
...
@@ -351,7 +351,7 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
/* FALLTHROUGH */
case
DeviceOutRequest
|
USB_REQ_CLEAR_FEATURE
:
case
DeviceOutRequest
|
USB_REQ_SET_FEATURE
:
dev_dbg
(
hcd
->
controller
,
"no device features yet yet
\n
"
);
dev_dbg
(
hcd
->
self
.
controller
,
"no device features yet yet
\n
"
);
break
;
case
DeviceRequest
|
USB_REQ_GET_CONFIGURATION
:
ubuf
[
0
]
=
1
;
...
...
@@ -394,7 +394,7 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
break
;
case
DeviceOutRequest
|
USB_REQ_SET_ADDRESS
:
// wValue == urb->dev->devaddr
dev_dbg
(
hcd
->
controller
,
"root hub device address %d
\n
"
,
dev_dbg
(
hcd
->
self
.
controller
,
"root hub device address %d
\n
"
,
wValue
);
break
;
...
...
@@ -409,7 +409,7 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
/* FALLTHROUGH */
case
EndpointOutRequest
|
USB_REQ_CLEAR_FEATURE
:
case
EndpointOutRequest
|
USB_REQ_SET_FEATURE
:
dev_dbg
(
hcd
->
controller
,
"no endpoint features yet
\n
"
);
dev_dbg
(
hcd
->
self
.
controller
,
"no endpoint features yet
\n
"
);
break
;
/* CLASS REQUESTS (and errors) */
...
...
@@ -423,12 +423,12 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
error:
/* "protocol stall" on error */
urb
->
status
=
-
EPIPE
;
dev_dbg
(
hcd
->
controller
,
"unsupported hub control message (maxchild %d)
\n
"
,
dev_dbg
(
hcd
->
self
.
controller
,
"unsupported hub control message (maxchild %d)
\n
"
,
urb
->
dev
->
maxchild
);
}
if
(
urb
->
status
)
{
urb
->
actual_length
=
0
;
dev_dbg
(
hcd
->
controller
,
"CTRL: TypeReq=0x%x val=0x%x idx=0x%x len=%d ==> %d
\n
"
,
dev_dbg
(
hcd
->
self
.
controller
,
"CTRL: TypeReq=0x%x val=0x%x idx=0x%x len=%d ==> %d
\n
"
,
typeReq
,
wValue
,
wIndex
,
wLength
,
urb
->
status
);
}
if
(
bufp
)
{
...
...
@@ -464,7 +464,7 @@ static int rh_status_urb (struct usb_hcd *hcd, struct urb *urb)
||
urb
->
status
!=
-
EINPROGRESS
||
urb
->
transfer_buffer_length
<
len
||
!
HCD_IS_RUNNING
(
hcd
->
state
))
{
dev_dbg
(
hcd
->
controller
,
dev_dbg
(
hcd
->
self
.
controller
,
"not queuing rh status urb, stat %d
\n
"
,
urb
->
status
);
return
-
EINVAL
;
...
...
@@ -1068,18 +1068,18 @@ static int hcd_submit_urb (struct urb *urb, int mem_flags)
/* lower level hcd code should use *_dma exclusively,
* unless it uses pio or talks to another transport.
*/
if
(
hcd
->
controller
->
dma_mask
)
{
if
(
hcd
->
self
.
controller
->
dma_mask
)
{
if
(
usb_pipecontrol
(
urb
->
pipe
)
&&
!
(
urb
->
transfer_flags
&
URB_NO_SETUP_DMA_MAP
))
urb
->
setup_dma
=
dma_map_single
(
hcd
->
controller
,
hcd
->
self
.
controller
,
urb
->
setup_packet
,
sizeof
(
struct
usb_ctrlrequest
),
DMA_TO_DEVICE
);
if
(
urb
->
transfer_buffer_length
!=
0
&&
!
(
urb
->
transfer_flags
&
URB_NO_TRANSFER_DMA_MAP
))
urb
->
transfer_dma
=
dma_map_single
(
hcd
->
controller
,
hcd
->
self
.
controller
,
urb
->
transfer_buffer
,
urb
->
transfer_buffer_length
,
usb_pipein
(
urb
->
pipe
)
...
...
@@ -1125,7 +1125,7 @@ unlink1 (struct usb_hcd *hcd, struct urb *urb)
/* failures "should" be harmless */
value
=
hcd
->
driver
->
urb_dequeue
(
hcd
,
urb
);
if
(
value
!=
0
)
dev_dbg
(
hcd
->
controller
,
dev_dbg
(
hcd
->
self
.
controller
,
"dequeue %p --> %d
\n
"
,
urb
,
value
);
}
...
...
@@ -1232,7 +1232,7 @@ static int hcd_unlink_urb (struct urb *urb)
* finish unlinking the initial failed usb_set_address().
*/
if
(
!
hcd
->
saw_irq
)
{
dev_warn
(
hcd
->
controller
,
"Unlink after no-IRQ? "
dev_warn
(
hcd
->
self
.
controller
,
"Unlink after no-IRQ? "
"Different ACPI or APIC settings may help."
"
\n
"
);
hcd
->
saw_irq
=
1
;
...
...
@@ -1244,7 +1244,8 @@ static int hcd_unlink_urb (struct urb *urb)
*/
if
(
!
(
urb
->
transfer_flags
&
URB_ASYNC_UNLINK
))
{
if
(
in_interrupt
())
{
dev_dbg
(
hcd
->
controller
,
"non-async unlink in_interrupt"
);
dev_dbg
(
hcd
->
self
.
controller
,
"non-async unlink in_interrupt"
);
retval
=
-
EWOULDBLOCK
;
goto
done
;
}
...
...
@@ -1363,7 +1364,7 @@ static void hcd_endpoint_disable (struct usb_device *udev, int endpoint)
if
(
tmp
==
-
EINPROGRESS
)
{
tmp
=
urb
->
pipe
;
unlink1
(
hcd
,
urb
);
dev_dbg
(
hcd
->
controller
,
dev_dbg
(
hcd
->
self
.
controller
,
"shutdown urb %p pipe %08x ep%d%s%s
\n
"
,
urb
,
tmp
,
usb_pipeendpoint
(
tmp
),
(
tmp
&
USB_DIR_IN
)
?
"in"
:
"out"
,
...
...
@@ -1417,7 +1418,7 @@ static int hcd_free_dev (struct usb_device *udev)
/* device driver problem with refcounts? */
if
(
!
list_empty
(
&
dev
->
urb_list
))
{
dev_dbg
(
hcd
->
controller
,
"free busy dev, %s devnum %d (bug!)
\n
"
,
dev_dbg
(
hcd
->
self
.
controller
,
"free busy dev, %s devnum %d (bug!)
\n
"
,
hcd
->
self
.
bus_name
,
udev
->
devnum
);
return
-
EINVAL
;
}
...
...
@@ -1474,15 +1475,16 @@ void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs
// It would catch exit/unlink paths for all urbs.
/* lower level hcd code should use *_dma exclusively */
if
(
hcd
->
controller
->
dma_mask
)
{
if
(
hcd
->
self
.
controller
->
dma_mask
)
{
if
(
usb_pipecontrol
(
urb
->
pipe
)
&&
!
(
urb
->
transfer_flags
&
URB_NO_SETUP_DMA_MAP
))
dma_unmap_single
(
hcd
->
controller
,
urb
->
setup_dma
,
dma_unmap_single
(
hcd
->
self
.
controller
,
urb
->
setup_dma
,
sizeof
(
struct
usb_ctrlrequest
),
DMA_TO_DEVICE
);
if
(
urb
->
transfer_buffer_length
!=
0
&&
!
(
urb
->
transfer_flags
&
URB_NO_TRANSFER_DMA_MAP
))
dma_unmap_single
(
hcd
->
controller
,
urb
->
transfer_dma
,
dma_unmap_single
(
hcd
->
self
.
controller
,
urb
->
transfer_dma
,
urb
->
transfer_buffer_length
,
usb_pipein
(
urb
->
pipe
)
?
DMA_FROM_DEVICE
...
...
@@ -1551,7 +1553,7 @@ static void hcd_panic (void *_hcd)
*/
void
usb_hc_died
(
struct
usb_hcd
*
hcd
)
{
dev_err
(
hcd
->
controller
,
"HC died; cleaning up
\n
"
);
dev_err
(
hcd
->
self
.
controller
,
"HC died; cleaning up
\n
"
);
/* clean up old urbs and devices; needs a task context */
INIT_WORK
(
&
hcd
->
work
,
hcd_panic
,
hcd
);
...
...
drivers/usb/core/hcd.h
View file @
cdb7bc8f
...
...
@@ -76,17 +76,14 @@ struct usb_hcd { /* usb_bus.hcpriv points to this */
unsigned
saw_irq
:
1
;
int
irq
;
/* irq allocated */
void
*
regs
;
/* device memory/io */
struct
device
*
controller
;
/* handle to hardware */
/* a few non-PCI controllers exist, mostly for OHCI */
struct
pci_dev
*
pdev
;
/* pci is typical */
#ifdef CONFIG_PCI
int
region
;
/* pci region for regs */
u32
pci_state
[
16
];
/* for PM state save */
#endif
#define HCD_BUFFER_POOLS 4
struct
pci
_pool
*
pool
[
HCD_BUFFER_POOLS
];
struct
dma
_pool
*
pool
[
HCD_BUFFER_POOLS
];
int
state
;
# define __ACTIVE 0x01
...
...
@@ -355,7 +352,7 @@ extern int usb_register_root_hub (struct usb_device *usb_dev,
static
inline
int
hcd_register_root
(
struct
usb_hcd
*
hcd
)
{
return
usb_register_root_hub
(
hcd_to_bus
(
hcd
)
->
root_hub
,
hcd
->
controller
);
hcd_to_bus
(
hcd
)
->
root_hub
,
hcd
->
self
.
controller
);
}
/*-------------------------------------------------------------------------*/
...
...
drivers/usb/core/hub.c
View file @
cdb7bc8f
...
...
@@ -405,9 +405,14 @@ static int hub_configure(struct usb_hub *hub,
hub
->
tt
.
hub
=
dev
;
break
;
case
2
:
ret
=
usb_set_interface
(
dev
,
0
,
1
);
if
(
ret
==
0
)
{
dev_dbg
(
hub_dev
,
"TT per port
\n
"
);
hub
->
tt
.
hub
=
dev
;
hub
->
tt
.
multi
=
1
;
}
else
dev_err
(
hub_dev
,
"Using single TT (err %d)
\n
"
,
ret
);
hub
->
tt
.
hub
=
dev
;
break
;
default:
dev_dbg
(
hub_dev
,
"Unrecognized hub protocol %d
\n
"
,
...
...
drivers/usb/core/message.c
View file @
cdb7bc8f
...
...
@@ -213,9 +213,8 @@ static void sg_clean (struct usb_sg_request *io)
static
void
sg_complete
(
struct
urb
*
urb
,
struct
pt_regs
*
regs
)
{
struct
usb_sg_request
*
io
=
(
struct
usb_sg_request
*
)
urb
->
context
;
unsigned
long
flags
;
spin_lock
_irqsave
(
&
io
->
lock
,
flags
);
spin_lock
(
&
io
->
lock
);
/* In 2.5 we require hcds' endpoint queues not to progress after fault
* reports, until the completion callback (this!) returns. That lets
...
...
@@ -269,7 +268,7 @@ static void sg_complete (struct urb *urb, struct pt_regs *regs)
if
(
!
io
->
count
)
complete
(
&
io
->
complete
);
spin_unlock
_irqrestore
(
&
io
->
lock
,
flags
);
spin_unlock
(
&
io
->
lock
);
}
...
...
@@ -441,12 +440,11 @@ int usb_sg_init (
*/
void
usb_sg_wait
(
struct
usb_sg_request
*
io
)
{
int
i
;
unsigned
long
flags
;
int
i
,
entries
=
io
->
entries
;
/* queue the urbs. */
spin_lock_irq
save
(
&
io
->
lock
,
flags
);
for
(
i
=
0
;
i
<
io
->
entries
&&
!
io
->
status
;
i
++
)
{
spin_lock_irq
(
&
io
->
lock
);
for
(
i
=
0
;
i
<
entries
&&
!
io
->
status
;
i
++
)
{
int
retval
;
io
->
urbs
[
i
]
->
dev
=
io
->
dev
;
...
...
@@ -455,7 +453,7 @@ void usb_sg_wait (struct usb_sg_request *io)
/* after we submit, let completions or cancelations fire;
* we handshake using io->status.
*/
spin_unlock_irq
restore
(
&
io
->
lock
,
flags
);
spin_unlock_irq
(
&
io
->
lock
);
switch
(
retval
)
{
/* maybe we retrying will recover */
case
-
ENXIO
:
// hc didn't queue this one
...
...
@@ -479,17 +477,25 @@ void usb_sg_wait (struct usb_sg_request *io)
/* fail any uncompleted urbs */
default:
spin_lock_irq
(
&
io
->
lock
);
io
->
count
-=
entries
-
i
;
if
(
io
->
status
==
-
EINPROGRESS
)
io
->
status
=
retval
;
if
(
io
->
count
==
0
)
complete
(
&
io
->
complete
);
spin_unlock_irq
(
&
io
->
lock
);
io
->
urbs
[
i
]
->
dev
=
0
;
io
->
urbs
[
i
]
->
status
=
retval
;
dev_dbg
(
&
io
->
dev
->
dev
,
"%s, submit --> %d
\n
"
,
__FUNCTION__
,
retval
);
usb_sg_cancel
(
io
);
}
spin_lock_irq
save
(
&
io
->
lock
,
flags
);
spin_lock_irq
(
&
io
->
lock
);
if
(
retval
&&
io
->
status
==
-
ECONNRESET
)
io
->
status
=
retval
;
}
spin_unlock_irq
restore
(
&
io
->
lock
,
flags
);
spin_unlock_irq
(
&
io
->
lock
);
/* OK, yes, this could be packaged as non-blocking.
* So could the submit loop above ... but it's easier to
...
...
drivers/usb/core/usb.c
View file @
cdb7bc8f
...
...
@@ -1152,12 +1152,19 @@ int usb_new_device(struct usb_device *dev)
config
=
dev
->
config
[
0
].
desc
.
bConfigurationValue
;
if
(
dev
->
descriptor
.
bNumConfigurations
!=
1
)
{
for
(
i
=
0
;
i
<
dev
->
descriptor
.
bNumConfigurations
;
i
++
)
{
struct
usb_interface_descriptor
*
desc
;
/* heuristic: Linux is more likely to have class
* drivers, so avoid vendor-specific interfaces.
*/
if
(
dev
->
config
[
i
].
interface
[
0
]
->
altsetting
->
desc
.
bInterfaceClass
==
USB_CLASS_VENDOR_SPEC
)
desc
=
&
dev
->
config
[
i
].
interface
[
0
]
->
altsetting
->
desc
;
if
(
desc
->
bInterfaceClass
==
USB_CLASS_VENDOR_SPEC
)
continue
;
/* COMM/2/all is CDC ACM, except 0xff is MSFT RNDIS */
if
(
desc
->
bInterfaceClass
==
USB_CLASS_COMM
&&
desc
->
bInterfaceSubClass
==
2
&&
desc
->
bInterfaceProtocol
==
0xff
)
continue
;
config
=
dev
->
config
[
i
].
desc
.
bConfigurationValue
;
break
;
...
...
drivers/usb/host/ehci-dbg.c
View file @
cdb7bc8f
...
...
@@ -19,13 +19,13 @@
/* this file is part of ehci-hcd.c */
#define ehci_dbg(ehci, fmt, args...) \
dev_dbg ((ehci)->hcd.controller , fmt , ## args )
dev_dbg ((ehci)->hcd.
self.
controller , fmt , ## args )
#define ehci_err(ehci, fmt, args...) \
dev_err ((ehci)->hcd.controller , fmt , ## args )
dev_err ((ehci)->hcd.
self.
controller , fmt , ## args )
#define ehci_info(ehci, fmt, args...) \
dev_info ((ehci)->hcd.controller , fmt , ## args )
dev_info ((ehci)->hcd.
self.
controller , fmt , ## args )
#define ehci_warn(ehci, fmt, args...) \
dev_warn ((ehci)->hcd.controller , fmt , ## args )
dev_warn ((ehci)->hcd.
self.
controller , fmt , ## args )
#ifdef EHCI_VERBOSE_DEBUG
# define vdbg dbg
...
...
@@ -367,7 +367,7 @@ static void qh_lines (
scratch
,
cpu_to_le32p
(
&
qh
->
hw_info2
),
cpu_to_le32p
(
&
qh
->
hw_token
),
mark
,
(
__constant_cpu_to_le32
(
QTD_TOGGLE
)
&
qh
->
hw_token
)
?
"data
0"
:
"data1
"
,
?
"data
1"
:
"data0
"
,
(
cpu_to_le32p
(
&
qh
->
hw_alt_next
)
>>
1
)
&
0x0f
);
size
-=
temp
;
next
+=
temp
;
...
...
@@ -625,7 +625,7 @@ show_registers (struct class_device *class_dev, char *buf)
i
=
HC_VERSION
(
readl
(
&
ehci
->
caps
->
hc_capbase
));
temp
=
scnprintf
(
next
,
size
,
"PCI device %s
\n
EHCI %x.%02x, hcd state %d (driver "
DRIVER_VERSION
")
\n
"
,
pci_name
(
hcd
->
pdev
),
pci_name
(
to_pci_dev
(
hcd
->
self
.
controller
)
),
i
>>
8
,
i
&
0x0ff
,
ehci
->
hcd
.
state
);
size
-=
temp
;
next
+=
temp
;
...
...
drivers/usb/host/ehci-hcd.c
View file @
cdb7bc8f
...
...
@@ -26,6 +26,7 @@
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/dmapool.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ioport.h>
...
...
@@ -67,6 +68,7 @@
*
* HISTORY:
*
* 2004-02-24 Replace pci_* with generic dma_* API calls (dsaxena@plexity.net)
* 2003-12-29 Rewritten high speed iso transfer support (by Michal Sojka,
* <sojkam@centrum.cz>, updates by DB).
*
...
...
@@ -288,13 +290,13 @@ static int bios_handoff (struct ehci_hcd *ehci, int where, u32 cap)
/* request handoff to OS */
cap
&=
1
<<
24
;
pci_write_config_dword
(
ehci
->
hcd
.
pdev
,
where
,
cap
);
pci_write_config_dword
(
to_pci_dev
(
ehci
->
hcd
.
self
.
controller
)
,
where
,
cap
);
/* and wait a while for it to happen */
do
{
wait_ms
(
10
);
msec
-=
10
;
pci_read_config_dword
(
ehci
->
hcd
.
pdev
,
where
,
&
cap
);
pci_read_config_dword
(
to_pci_dev
(
ehci
->
hcd
.
self
.
controller
)
,
where
,
&
cap
);
}
while
((
cap
&
(
1
<<
16
))
&&
msec
);
if
(
cap
&
(
1
<<
16
))
{
ehci_err
(
ehci
,
"BIOS handoff failed (%d, %04x)
\n
"
,
...
...
@@ -339,7 +341,7 @@ static int ehci_hc_reset (struct usb_hcd *hcd)
while
(
temp
)
{
u32
cap
;
pci_read_config_dword
(
ehci
->
hcd
.
pdev
,
temp
,
&
cap
);
pci_read_config_dword
(
to_pci_dev
(
ehci
->
hcd
.
self
.
controller
)
,
temp
,
&
cap
);
ehci_dbg
(
ehci
,
"capability %04x at %02x
\n
"
,
cap
,
temp
);
switch
(
cap
&
0xff
)
{
case
1
:
/* BIOS/SMM/... handoff */
...
...
@@ -378,7 +380,7 @@ static int ehci_start (struct usb_hcd *hcd)
* periodic_size can shrink by USBCMD update if hcc_params allows.
*/
ehci
->
periodic_size
=
DEFAULT_I_TDPS
;
if
((
retval
=
ehci_mem_init
(
ehci
,
SLAB
_KERNEL
))
<
0
)
if
((
retval
=
ehci_mem_init
(
ehci
,
GFP
_KERNEL
))
<
0
)
return
retval
;
/* controllers may cache some of the periodic schedule ... */
...
...
@@ -433,13 +435,13 @@ static int ehci_start (struct usb_hcd *hcd)
writel
(
0
,
&
ehci
->
regs
->
segment
);
#if 0
// this is deeply broken on almost all architectures
if (!pci_set_dma_mask (
ehci->hcd.pdev
, 0xffffffffffffffffULL))
if (!pci_set_dma_mask (
to_pci_dev(ehci->hcd.self.controller)
, 0xffffffffffffffffULL))
ehci_info (ehci, "enabled 64bit PCI DMA\n");
#endif
}
/* help hc dma work well with cachelines */
pci_set_mwi
(
ehci
->
hcd
.
pdev
);
pci_set_mwi
(
to_pci_dev
(
ehci
->
hcd
.
self
.
controller
)
);
/* clear interrupt enables, set irq latency */
temp
=
readl
(
&
ehci
->
regs
->
command
)
&
0x0fff
;
...
...
@@ -493,7 +495,7 @@ static int ehci_start (struct usb_hcd *hcd)
readl
(
&
ehci
->
regs
->
command
);
/* unblock posted write */
/* PCI Serial Bus Release Number is at 0x60 offset */
pci_read_config_byte
(
hcd
->
pdev
,
0x60
,
&
tempbyte
);
pci_read_config_byte
(
to_pci_dev
(
hcd
->
self
.
controller
)
,
0x60
,
&
tempbyte
);
temp
=
HC_VERSION
(
readl
(
&
ehci
->
caps
->
hc_capbase
));
ehci_info
(
ehci
,
"USB %x.%x enabled, EHCI %x.%02x, driver %s
\n
"
,
...
...
@@ -758,7 +760,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs)
* non-error returns are a promise to giveback() the urb later
* we drop ownership so next owner (or urb unlink) can get it
*
* urb + dev is in hcd
_dev
.urb_list
* urb + dev is in hcd
.self.controller
.urb_list
* we're queueing TDs onto software and hardware lists
*
* hcd-specific init for hcpriv hasn't been done yet
...
...
drivers/usb/host/ehci-hub.c
View file @
cdb7bc8f
...
...
@@ -113,7 +113,7 @@ ehci_hub_descriptor (
u16
temp
;
desc
->
bDescriptorType
=
0x29
;
desc
->
bPwrOn2PwrGood
=
10
;
/*
FIXME: f(system power)
*/
desc
->
bPwrOn2PwrGood
=
10
;
/*
ehci 1.0, 2.3.9 says 20ms max
*/
desc
->
bHubContrCurrent
=
0
;
desc
->
bNbrPorts
=
ports
;
...
...
drivers/usb/host/ehci-mem.c
View file @
cdb7bc8f
...
...
@@ -24,7 +24,7 @@
* There's basically three types of memory:
* - data used only by the HCD ... kmalloc is fine
* - async and periodic schedules, shared by HC and HCD ... these
* need to use
pci_pool or pci_alloc_consist
ent
* need to use
dma_pool or dma_alloc_coher
ent
* - driver buffers, read/written by HC ... single shot DMA mapped
*
* There's also PCI "register" data, which is memory mapped.
...
...
@@ -74,7 +74,7 @@ static struct ehci_qtd *ehci_qtd_alloc (struct ehci_hcd *ehci, int flags)
struct
ehci_qtd
*
qtd
;
dma_addr_t
dma
;
qtd
=
pci
_pool_alloc
(
ehci
->
qtd_pool
,
flags
,
&
dma
);
qtd
=
dma
_pool_alloc
(
ehci
->
qtd_pool
,
flags
,
&
dma
);
if
(
qtd
!=
0
)
{
ehci_qtd_init
(
qtd
,
dma
);
}
...
...
@@ -83,7 +83,7 @@ static struct ehci_qtd *ehci_qtd_alloc (struct ehci_hcd *ehci, int flags)
static
inline
void
ehci_qtd_free
(
struct
ehci_hcd
*
ehci
,
struct
ehci_qtd
*
qtd
)
{
pci
_pool_free
(
ehci
->
qtd_pool
,
qtd
,
qtd
->
qtd_dma
);
dma
_pool_free
(
ehci
->
qtd_pool
,
qtd
,
qtd
->
qtd_dma
);
}
...
...
@@ -93,7 +93,7 @@ static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, int flags)
dma_addr_t
dma
;
qh
=
(
struct
ehci_qh
*
)
pci
_pool_alloc
(
ehci
->
qh_pool
,
flags
,
&
dma
);
dma
_pool_alloc
(
ehci
->
qh_pool
,
flags
,
&
dma
);
if
(
!
qh
)
return
qh
;
...
...
@@ -107,7 +107,7 @@ static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, int flags)
qh
->
dummy
=
ehci_qtd_alloc
(
ehci
,
flags
);
if
(
qh
->
dummy
==
0
)
{
ehci_dbg
(
ehci
,
"no dummy td
\n
"
);
pci
_pool_free
(
ehci
->
qh_pool
,
qh
,
qh
->
qh_dma
);
dma
_pool_free
(
ehci
->
qh_pool
,
qh
,
qh
->
qh_dma
);
qh
=
0
;
}
return
qh
;
...
...
@@ -132,7 +132,7 @@ static void qh_put (struct ehci_hcd *ehci, struct ehci_qh *qh)
if
(
qh
->
dummy
)
ehci_qtd_free
(
ehci
,
qh
->
dummy
);
usb_put_dev
(
qh
->
dev
);
pci
_pool_free
(
ehci
->
qh_pool
,
qh
,
qh
->
qh_dma
);
dma
_pool_free
(
ehci
->
qh_pool
,
qh
,
qh
->
qh_dma
);
}
/*-------------------------------------------------------------------------*/
...
...
@@ -148,26 +148,26 @@ static void ehci_mem_cleanup (struct ehci_hcd *ehci)
qh_put
(
ehci
,
ehci
->
async
);
ehci
->
async
=
0
;
/*
PCI
consistent memory and pools */
/*
DMA
consistent memory and pools */
if
(
ehci
->
qtd_pool
)
pci
_pool_destroy
(
ehci
->
qtd_pool
);
dma
_pool_destroy
(
ehci
->
qtd_pool
);
ehci
->
qtd_pool
=
0
;
if
(
ehci
->
qh_pool
)
{
pci
_pool_destroy
(
ehci
->
qh_pool
);
dma
_pool_destroy
(
ehci
->
qh_pool
);
ehci
->
qh_pool
=
0
;
}
if
(
ehci
->
itd_pool
)
pci
_pool_destroy
(
ehci
->
itd_pool
);
dma
_pool_destroy
(
ehci
->
itd_pool
);
ehci
->
itd_pool
=
0
;
if
(
ehci
->
sitd_pool
)
pci
_pool_destroy
(
ehci
->
sitd_pool
);
dma
_pool_destroy
(
ehci
->
sitd_pool
);
ehci
->
sitd_pool
=
0
;
if
(
ehci
->
periodic
)
pci_free_consistent
(
ehci
->
hcd
.
pdev
,
dma_free_coherent
(
ehci
->
hcd
.
self
.
controller
,
ehci
->
periodic_size
*
sizeof
(
u32
),
ehci
->
periodic
,
ehci
->
periodic_dma
);
ehci
->
periodic
=
0
;
...
...
@@ -184,7 +184,8 @@ static int ehci_mem_init (struct ehci_hcd *ehci, int flags)
int
i
;
/* QTDs for control/bulk/intr transfers */
ehci
->
qtd_pool
=
pci_pool_create
(
"ehci_qtd"
,
ehci
->
hcd
.
pdev
,
ehci
->
qtd_pool
=
dma_pool_create
(
"ehci_qtd"
,
ehci
->
hcd
.
self
.
controller
,
sizeof
(
struct
ehci_qtd
),
32
/* byte alignment (for hw parts) */
,
4096
/* can't cross 4K */
);
...
...
@@ -193,7 +194,8 @@ static int ehci_mem_init (struct ehci_hcd *ehci, int flags)
}
/* QHs for control/bulk/intr transfers */
ehci
->
qh_pool
=
pci_pool_create
(
"ehci_qh"
,
ehci
->
hcd
.
pdev
,
ehci
->
qh_pool
=
dma_pool_create
(
"ehci_qh"
,
ehci
->
hcd
.
self
.
controller
,
sizeof
(
struct
ehci_qh
),
32
/* byte alignment (for hw parts) */
,
4096
/* can't cross 4K */
);
...
...
@@ -206,7 +208,8 @@ static int ehci_mem_init (struct ehci_hcd *ehci, int flags)
}
/* ITD for high speed ISO transfers */
ehci
->
itd_pool
=
pci_pool_create
(
"ehci_itd"
,
ehci
->
hcd
.
pdev
,
ehci
->
itd_pool
=
dma_pool_create
(
"ehci_itd"
,
ehci
->
hcd
.
self
.
controller
,
sizeof
(
struct
ehci_itd
),
32
/* byte alignment (for hw parts) */
,
4096
/* can't cross 4K */
);
...
...
@@ -215,7 +218,8 @@ static int ehci_mem_init (struct ehci_hcd *ehci, int flags)
}
/* SITD for full/low speed split ISO transfers */
ehci
->
sitd_pool
=
pci_pool_create
(
"ehci_sitd"
,
ehci
->
hcd
.
pdev
,
ehci
->
sitd_pool
=
dma_pool_create
(
"ehci_sitd"
,
ehci
->
hcd
.
self
.
controller
,
sizeof
(
struct
ehci_sitd
),
32
/* byte alignment (for hw parts) */
,
4096
/* can't cross 4K */
);
...
...
@@ -225,9 +229,9 @@ static int ehci_mem_init (struct ehci_hcd *ehci, int flags)
/* Hardware periodic table */
ehci
->
periodic
=
(
u32
*
)
pci_alloc_consistent
(
ehci
->
hcd
.
pdev
,
dma_alloc_coherent
(
ehci
->
hcd
.
self
.
controller
,
ehci
->
periodic_size
*
sizeof
(
u32
),
&
ehci
->
periodic_dma
);
&
ehci
->
periodic_dma
,
0
);
if
(
ehci
->
periodic
==
0
)
{
goto
fail
;
}
...
...
drivers/usb/host/ehci-q.c
View file @
cdb7bc8f
...
...
@@ -776,7 +776,7 @@ static struct ehci_qh *qh_append_tds (
qh
=
(
struct
ehci_qh
*
)
*
ptr
;
if
(
unlikely
(
qh
==
0
))
{
/* can't sleep here, we have ehci->lock... */
qh
=
qh_make
(
ehci
,
urb
,
SLAB
_ATOMIC
);
qh
=
qh_make
(
ehci
,
urb
,
GFP
_ATOMIC
);
*
ptr
=
qh
;
}
if
(
likely
(
qh
!=
0
))
{
...
...
drivers/usb/host/ehci-sched.c
View file @
cdb7bc8f
...
...
@@ -115,6 +115,7 @@ periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe)
/* ... or C-mask? */
if
(
q
->
qh
->
hw_info2
&
cpu_to_le32
(
1
<<
(
8
+
uframe
)))
usecs
+=
q
->
qh
->
c_usecs
;
hw_p
=
&
q
->
qh
->
hw_next
;
q
=
&
q
->
qh
->
qh_next
;
break
;
case
Q_TYPE_FSTN
:
...
...
@@ -122,37 +123,35 @@ periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe)
* bandwidth from the previous frame
*/
if
(
q
->
fstn
->
hw_prev
!=
EHCI_LIST_END
)
{
dbg
(
"not counting FSTN bandwidth yet ...
"
);
ehci_dbg
(
ehci
,
"ignoring FSTN cost ...
\n
"
);
}
hw_p
=
&
q
->
fstn
->
hw_next
;
q
=
&
q
->
fstn
->
fstn_next
;
break
;
case
Q_TYPE_ITD
:
usecs
+=
q
->
itd
->
usecs
[
uframe
];
hw_p
=
&
q
->
itd
->
hw_next
;
q
=
&
q
->
itd
->
itd_next
;
break
;
#ifdef have_split_iso
case
Q_TYPE_SITD
:
temp
=
q
->
sitd
->
hw_fullspeed_ep
&
__constant_cpu_to_le32
(
1
<<
31
);
// FIXME: this doesn't count data bytes right...
/* is it in the S-mask? (count SPLIT, DATA) */
if
(
q
->
sitd
->
hw_uframe
&
cpu_to_le32
(
1
<<
uframe
))
{
if
(
temp
)
usecs
+=
HS_USECS
(
188
);
else
usecs
+=
HS_USECS
(
1
);
if
(
q
->
sitd
->
hw_fullspeed_ep
&
__constant_cpu_to_le32
(
1
<<
31
))
usecs
+=
q
->
sitd
->
stream
->
usecs
;
else
/* worst case for OUT start-split */
usecs
+=
HS_USECS_ISO
(
188
);
}
/* ... C-mask? (count CSPLIT, DATA) */
if
(
q
->
sitd
->
hw_uframe
&
cpu_to_le32
(
1
<<
(
8
+
uframe
)))
{
if
(
temp
)
usecs
+=
HS_USECS
(
0
);
else
usecs
+=
HS_USECS
(
188
);
/* worst case for IN complete-split */
usecs
+=
q
->
sitd
->
stream
->
c_usecs
;
}
hw_p
=
&
q
->
sitd
->
hw_next
;
q
=
&
q
->
sitd
->
sitd_next
;
break
;
#endif
/* have_split_iso */
...
...
@@ -170,6 +169,93 @@ periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe)
/*-------------------------------------------------------------------------*/
static
int
same_tt
(
struct
usb_device
*
dev1
,
struct
usb_device
*
dev2
)
{
if
(
!
dev1
->
tt
||
!
dev2
->
tt
)
return
0
;
if
(
dev1
->
tt
!=
dev2
->
tt
)
return
0
;
if
(
dev1
->
tt
->
multi
)
return
dev1
->
ttport
==
dev2
->
ttport
;
else
return
1
;
}
/* return true iff the device's transaction translator is available
* for a periodic transfer starting at the specified frame, using
* all the uframes in the mask.
*/
static
int
tt_no_collision
(
struct
ehci_hcd
*
ehci
,
unsigned
period
,
struct
usb_device
*
dev
,
unsigned
frame
,
u32
uf_mask
)
{
if
(
period
==
0
)
/* error */
return
0
;
/* note bandwidth wastage: split never follows csplit
* (different dev or endpoint) until the next uframe.
* calling convention doesn't make that distinction.
*/
for
(;
frame
<
ehci
->
periodic_size
;
frame
+=
period
)
{
union
ehci_shadow
here
;
u32
type
;
here
=
ehci
->
pshadow
[
frame
];
type
=
Q_NEXT_TYPE
(
ehci
->
periodic
[
frame
]);
while
(
here
.
ptr
)
{
switch
(
type
)
{
case
Q_TYPE_ITD
:
type
=
Q_NEXT_TYPE
(
here
.
itd
->
hw_next
);
here
=
here
.
itd
->
itd_next
;
continue
;
case
Q_TYPE_QH
:
if
(
same_tt
(
dev
,
here
.
qh
->
dev
))
{
u32
mask
;
mask
=
le32_to_cpu
(
here
.
qh
->
hw_info2
);
/* "knows" no gap is needed */
mask
|=
mask
>>
8
;
if
(
mask
&
uf_mask
)
break
;
}
type
=
Q_NEXT_TYPE
(
here
.
qh
->
hw_next
);
here
=
here
.
qh
->
qh_next
;
continue
;
case
Q_TYPE_SITD
:
if
(
same_tt
(
dev
,
here
.
itd
->
urb
->
dev
))
{
u16
mask
;
mask
=
le32_to_cpu
(
here
.
sitd
->
hw_uframe
);
/* FIXME assumes no gap for IN! */
mask
|=
mask
>>
8
;
if
(
mask
&
uf_mask
)
break
;
}
type
=
Q_NEXT_TYPE
(
here
.
qh
->
hw_next
);
here
=
here
.
sitd
->
sitd_next
;
break
;
// case Q_TYPE_FSTN:
default:
ehci_dbg
(
ehci
,
"periodic frame %d bogus type %d
\n
"
,
frame
,
type
);
}
/* collision or error */
return
0
;
}
}
/* no collision */
return
1
;
}
/*-------------------------------------------------------------------------*/
static
int
enable_periodic
(
struct
ehci_hcd
*
ehci
)
{
u32
cmd
;
...
...
@@ -490,36 +576,11 @@ static int intr_submit (
return
status
;
}
static
unsigned
intr_complete
(
struct
ehci_hcd
*
ehci
,
unsigned
frame
,
struct
ehci_qh
*
qh
,
struct
pt_regs
*
regs
)
{
unsigned
count
;
/* nothing to report? */
if
(
likely
((
qh
->
hw_token
&
__constant_cpu_to_le32
(
QTD_STS_ACTIVE
))
!=
0
))
return
0
;
if
(
unlikely
(
list_empty
(
&
qh
->
qtd_list
)))
{
dbg
(
"intr qh %p no TDs?"
,
qh
);
return
0
;
}
/* handle any completions */
count
=
qh_completions
(
ehci
,
qh
,
regs
);
if
(
unlikely
(
list_empty
(
&
qh
->
qtd_list
)))
intr_deschedule
(
ehci
,
qh
,
0
);
return
count
;
}
/*-------------------------------------------------------------------------*/
static
inline
struct
ehci_iso_stream
*
/* ehci_iso_stream ops work with both ITD and SITD */
static
struct
ehci_iso_stream
*
iso_stream_alloc
(
int
mem_flags
)
{
struct
ehci_iso_stream
*
stream
;
...
...
@@ -527,15 +588,15 @@ iso_stream_alloc (int mem_flags)
stream
=
kmalloc
(
sizeof
*
stream
,
mem_flags
);
if
(
likely
(
stream
!=
0
))
{
memset
(
stream
,
0
,
sizeof
(
*
stream
));
INIT_LIST_HEAD
(
&
stream
->
i
td_list
);
INIT_LIST_HEAD
(
&
stream
->
free_
itd_
list
);
INIT_LIST_HEAD
(
&
stream
->
td_list
);
INIT_LIST_HEAD
(
&
stream
->
free_list
);
stream
->
next_uframe
=
-
1
;
stream
->
refcount
=
1
;
}
return
stream
;
}
static
inline
void
static
void
iso_stream_init
(
struct
ehci_iso_stream
*
stream
,
struct
usb_device
*
dev
,
...
...
@@ -543,8 +604,10 @@ iso_stream_init (
unsigned
interval
)
{
static
const
u8
smask_out
[]
=
{
0x01
,
0x03
,
0x07
,
0x0f
,
0x1f
,
0x3f
};
u32
buf1
;
unsigned
epnum
,
maxp
,
multi
;
unsigned
epnum
,
maxp
;
int
is_input
;
long
bandwidth
;
...
...
@@ -562,17 +625,16 @@ iso_stream_init (
buf1
=
0
;
}
multi
=
hb_mult
(
maxp
);
/* knows about ITD vs SITD */
if
(
dev
->
speed
==
USB_SPEED_HIGH
)
{
unsigned
multi
=
hb_mult
(
maxp
);
stream
->
highspeed
=
1
;
maxp
=
max_packet
(
maxp
);
buf1
|=
maxp
;
maxp
*=
multi
;
stream
->
dev
=
(
struct
hcd_dev
*
)
dev
->
hcpriv
;
stream
->
bEndpointAddress
=
is_input
|
epnum
;
stream
->
interval
=
interval
;
stream
->
maxp
=
maxp
;
stream
->
buf0
=
cpu_to_le32
((
epnum
<<
8
)
|
dev
->
devnum
);
stream
->
buf1
=
cpu_to_le32
(
buf1
);
stream
->
buf2
=
cpu_to_le32
(
multi
);
...
...
@@ -583,7 +645,42 @@ iso_stream_init (
stream
->
usecs
=
HS_USECS_ISO
(
maxp
);
bandwidth
=
stream
->
usecs
*
8
;
bandwidth
/=
1
<<
(
interval
-
1
);
}
else
{
u32
addr
;
addr
=
dev
->
ttport
<<
24
;
addr
|=
dev
->
tt
->
hub
->
devnum
<<
16
;
addr
|=
epnum
<<
8
;
addr
|=
dev
->
devnum
;
stream
->
usecs
=
HS_USECS_ISO
(
maxp
);
if
(
is_input
)
{
u32
tmp
;
addr
|=
1
<<
31
;
stream
->
c_usecs
=
stream
->
usecs
;
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
);
}
else
stream
->
raw_mask
=
smask_out
[
maxp
/
188
];
bandwidth
=
stream
->
usecs
+
stream
->
c_usecs
;
bandwidth
/=
1
<<
(
interval
+
2
);
/* stream->splits gets created from raw_mask later */
stream
->
address
=
cpu_to_le32
(
addr
);
}
stream
->
bandwidth
=
bandwidth
;
stream
->
udev
=
dev
;
stream
->
bEndpointAddress
=
is_input
|
epnum
;
stream
->
interval
=
interval
;
stream
->
maxp
=
maxp
;
}
static
void
...
...
@@ -596,21 +693,22 @@ iso_stream_put(struct ehci_hcd *ehci, struct ehci_iso_stream *stream)
*/
if
(
stream
->
refcount
==
1
)
{
int
is_in
;
struct
hcd_dev
*
dev
=
stream
->
udev
->
hcpriv
;
// BUG_ON (!list_empty(&stream->
i
td_list));
// BUG_ON (!list_empty(&stream->td_list));
while
(
!
list_empty
(
&
stream
->
free_
itd_
list
))
{
while
(
!
list_empty
(
&
stream
->
free_list
))
{
struct
ehci_itd
*
itd
;
itd
=
list_entry
(
stream
->
free_
itd_
list
.
next
,
itd
=
list_entry
(
stream
->
free_list
.
next
,
struct
ehci_itd
,
itd_list
);
list_del
(
&
itd
->
itd_list
);
pci
_pool_free
(
ehci
->
itd_pool
,
itd
,
itd
->
itd_dma
);
dma
_pool_free
(
ehci
->
itd_pool
,
itd
,
itd
->
itd_dma
);
}
is_in
=
(
stream
->
bEndpointAddress
&
USB_DIR_IN
)
?
0x10
:
0
;
stream
->
bEndpointAddress
&=
0x0f
;
stream
->
dev
->
ep
[
is_in
+
stream
->
bEndpointAddress
]
=
0
;
dev
->
ep
[
is_in
+
stream
->
bEndpointAddress
]
=
0
;
if
(
stream
->
rescheduled
)
{
ehci_info
(
ehci
,
"ep%d%s-iso rescheduled "
...
...
@@ -676,24 +774,26 @@ iso_stream_find (struct ehci_hcd *ehci, struct urb *urb)
/*-------------------------------------------------------------------------*/
static
inline
struct
ehci_itd_sched
*
itd_sched_alloc
(
unsigned
packets
,
int
mem_flags
)
/* ehci_iso_sched ops can be shared, ITD-only, or SITD-only */
static
struct
ehci_iso_sched
*
iso_sched_alloc
(
unsigned
packets
,
int
mem_flags
)
{
struct
ehci_i
td_sched
*
itd
_sched
;
int
size
=
sizeof
*
i
td
_sched
;
size
+=
packets
*
sizeof
(
struct
ehci_iso_
uframe
);
i
td
_sched
=
kmalloc
(
size
,
mem_flags
);
if
(
likely
(
i
td
_sched
!=
0
))
{
memset
(
i
td
_sched
,
0
,
size
);
INIT_LIST_HEAD
(
&
i
td_sched
->
i
td_list
);
struct
ehci_i
so_sched
*
iso
_sched
;
int
size
=
sizeof
*
i
so
_sched
;
size
+=
packets
*
sizeof
(
struct
ehci_iso_
packet
);
i
so
_sched
=
kmalloc
(
size
,
mem_flags
);
if
(
likely
(
i
so
_sched
!=
0
))
{
memset
(
i
so
_sched
,
0
,
size
);
INIT_LIST_HEAD
(
&
i
so_sched
->
td_list
);
}
return
i
td
_sched
;
return
i
so
_sched
;
}
static
in
t
static
in
line
void
itd_sched_init
(
struct
ehci_i
td_sched
*
itd
_sched
,
struct
ehci_i
so_sched
*
iso
_sched
,
struct
ehci_iso_stream
*
stream
,
struct
urb
*
urb
)
...
...
@@ -702,13 +802,13 @@ itd_sched_init (
dma_addr_t
dma
=
urb
->
transfer_dma
;
/* how many uframes are needed for these transfers */
i
td
_sched
->
span
=
urb
->
number_of_packets
*
stream
->
interval
;
i
so
_sched
->
span
=
urb
->
number_of_packets
*
stream
->
interval
;
/* figure out per-uframe itd fields that we'll need later
* when we fit new itds into the schedule.
*/
for
(
i
=
0
;
i
<
urb
->
number_of_packets
;
i
++
)
{
struct
ehci_iso_
uframe
*
uframe
=
&
itd
_sched
->
packet
[
i
];
struct
ehci_iso_
packet
*
uframe
=
&
iso
_sched
->
packet
[
i
];
unsigned
length
;
dma_addr_t
buf
;
u32
trans
;
...
...
@@ -718,7 +818,8 @@ itd_sched_init (
trans
=
EHCI_ISOC_ACTIVE
;
trans
|=
buf
&
0x0fff
;
if
(
unlikely
((
i
+
1
)
==
urb
->
number_of_packets
))
if
(
unlikely
(((
i
+
1
)
==
urb
->
number_of_packets
))
&&
!
(
urb
->
transfer_flags
&
URB_NO_INTERRUPT
))
trans
|=
EHCI_ITD_IOC
;
trans
|=
length
<<
16
;
uframe
->
transaction
=
cpu_to_le32
(
trans
);
...
...
@@ -729,17 +830,19 @@ itd_sched_init (
if
(
unlikely
((
uframe
->
bufp
!=
(
buf
&
~
(
u64
)
0x0fff
))))
uframe
->
cross
=
1
;
}
return
0
;
}
static
void
i
td
_sched_free
(
i
so
_sched_free
(
struct
ehci_iso_stream
*
stream
,
struct
ehci_i
td_sched
*
itd
_sched
struct
ehci_i
so_sched
*
iso
_sched
)
{
list_splice
(
&
itd_sched
->
itd_list
,
&
stream
->
free_itd_list
);
kfree
(
itd_sched
);
if
(
!
iso_sched
)
return
;
// caller must hold ehci->lock!
list_splice
(
&
iso_sched
->
td_list
,
&
stream
->
free_list
);
kfree
(
iso_sched
);
}
static
int
...
...
@@ -751,110 +854,201 @@ itd_urb_transaction (
)
{
struct
ehci_itd
*
itd
;
int
status
;
dma_addr_t
itd_dma
;
int
i
;
unsigned
num_itds
;
struct
ehci_i
td_sched
*
itd_
sched
;
struct
ehci_i
so_sched
*
sched
;
itd_sched
=
itd
_sched_alloc
(
urb
->
number_of_packets
,
mem_flags
);
if
(
unlikely
(
itd_
sched
==
0
))
sched
=
iso
_sched_alloc
(
urb
->
number_of_packets
,
mem_flags
);
if
(
unlikely
(
sched
==
0
))
return
-
ENOMEM
;
status
=
itd_sched_init
(
itd_sched
,
stream
,
urb
);
if
(
unlikely
(
status
!=
0
))
{
itd_sched_free
(
stream
,
itd_sched
);
return
status
;
}
itd_sched_init
(
sched
,
stream
,
urb
);
if
(
urb
->
interval
<
8
)
num_itds
=
1
+
(
itd_
sched
->
span
+
7
)
/
8
;
num_itds
=
1
+
(
sched
->
span
+
7
)
/
8
;
else
num_itds
=
urb
->
number_of_packets
;
/* allocate/init ITDs */
for
(
i
=
0
;
i
<
num_itds
;
i
++
)
{
/* free_
itd_
list.next might be cache-hot ... but maybe
/* free_list.next might be cache-hot ... but maybe
* the HC caches it too. avoid that issue for now.
*/
/* prefer previously-allocated itds */
if
(
likely
(
!
list_empty
(
&
stream
->
free_
itd_
list
)))
{
itd
=
list_entry
(
stream
->
free_
itd_
list
.
prev
,
if
(
likely
(
!
list_empty
(
&
stream
->
free_list
)))
{
itd
=
list_entry
(
stream
->
free_list
.
prev
,
struct
ehci_itd
,
itd_list
);
list_del
(
&
itd
->
itd_list
);
itd_dma
=
itd
->
itd_dma
;
}
else
itd
=
pci
_pool_alloc
(
ehci
->
itd_pool
,
mem_flags
,
itd
=
dma
_pool_alloc
(
ehci
->
itd_pool
,
mem_flags
,
&
itd_dma
);
if
(
unlikely
(
0
==
itd
))
{
i
td_sched_free
(
stream
,
itd_
sched
);
i
so_sched_free
(
stream
,
sched
);
return
-
ENOMEM
;
}
memset
(
itd
,
0
,
sizeof
*
itd
);
itd
->
itd_dma
=
itd_dma
;
list_add
(
&
itd
->
itd_list
,
&
itd_sched
->
i
td_list
);
list_add
(
&
itd
->
itd_list
,
&
sched
->
td_list
);
}
/* temporarily store schedule info in hcpriv */
urb
->
hcpriv
=
itd_
sched
;
urb
->
hcpriv
=
sched
;
urb
->
error_count
=
0
;
return
0
;
}
/*-------------------------------------------------------------------------*/
static
inline
int
itd_slot_ok
(
struct
ehci_hcd
*
ehci
,
u32
mod
,
u32
uframe
,
u32
end
,
u8
usecs
,
u32
period
)
{
do
{
/* can't commit more than 80% periodic == 100 usec */
if
(
periodic_usecs
(
ehci
,
uframe
>>
3
,
uframe
&
0x7
)
>
(
100
-
usecs
))
return
0
;
/* we know urb->interval is 2^N uframes */
uframe
+=
period
;
uframe
%=
mod
;
}
while
(
uframe
!=
end
);
return
1
;
}
static
inline
int
sitd_slot_ok
(
struct
ehci_hcd
*
ehci
,
u32
mod
,
struct
ehci_iso_stream
*
stream
,
u32
uframe
,
u32
end
,
struct
ehci_iso_sched
*
sched
,
u32
period_uframes
)
{
u32
mask
,
tmp
;
u32
frame
,
uf
;
mask
=
stream
->
raw_mask
<<
(
uframe
&
7
);
/* for IN, don't wrap CSPLIT into the next frame */
if
(
mask
&
~
0xffff
)
return
0
;
/* this multi-pass logic is simple, but performance may
* suffer when the schedule data isn't cached.
*/
/* check bandwidth */
do
{
u32
max_used
;
frame
=
uframe
>>
3
;
uf
=
uframe
&
7
;
/* check starts (OUT uses more than one) */
max_used
=
100
-
stream
->
usecs
;
for
(
tmp
=
stream
->
raw_mask
&
0xff
;
tmp
;
tmp
>>=
1
,
uf
++
)
{
if
(
periodic_usecs
(
ehci
,
frame
,
uf
)
>
max_used
)
return
0
;
}
/* for IN, check CSPLIT */
if
(
stream
->
c_usecs
)
{
max_used
=
100
-
stream
->
c_usecs
;
do
{
/* tt is busy in the gap before CSPLIT */
tmp
=
1
<<
uf
;
mask
|=
tmp
;
tmp
<<=
8
;
if
(
stream
->
raw_mask
&
tmp
)
break
;
}
while
(
++
uf
<
8
);
if
(
periodic_usecs
(
ehci
,
frame
,
uf
)
>
max_used
)
return
0
;
}
/* we know urb->interval is 2^N uframes */
uframe
+=
period_uframes
;
uframe
%=
mod
;
}
while
(
uframe
!=
end
);
/* tt must be idle for start(s), any gap, and csplit */
if
(
!
tt_no_collision
(
ehci
,
period_uframes
,
stream
->
udev
,
frame
,
mask
))
return
0
;
stream
->
splits
=
stream
->
raw_mask
<<
(
uframe
&
7
);
cpu_to_le32s
(
&
stream
->
splits
);
return
1
;
}
/*
* This scheduler plans almost as far into the future as it has actual
* periodic schedule slots. (Affected by TUNE_FLS, which defaults to
* "as small as possible" to be cache-friendlier.) That limits the size
* transfers you can stream reliably; avoid more than 64 msec per urb.
* Also avoid queue depths of less than the system's worst irq latency.
* Also avoid queue depths of less than ehci's worst irq latency (affected
* by the per-urb URB_NO_INTERRUPT hint, the log2_irq_thresh module parameter,
* and other factors); or more than about 230 msec total (for portability,
* given EHCI_TUNE_FLS and the slop). Or, write a smarter scheduler!
*/
#define SCHEDULE_SLOP 10
/* frames */
static
int
i
td
_stream_schedule
(
i
so
_stream_schedule
(
struct
ehci_hcd
*
ehci
,
struct
urb
*
urb
,
struct
ehci_iso_stream
*
stream
)
{
u32
now
,
start
,
end
,
max
;
u32
now
,
start
,
end
,
max
,
period
;
int
status
;
unsigned
mod
=
ehci
->
periodic_size
<<
3
;
struct
ehci_i
td_sched
*
itd_
sched
=
urb
->
hcpriv
;
struct
ehci_i
so_sched
*
sched
=
urb
->
hcpriv
;
if
(
unlikely
(
itd_sched
->
span
>
(
mod
-
8
*
SCHEDULE_SLOP
)
))
{
if
(
sched
->
span
>
(
mod
-
8
*
SCHEDULE_SLOP
))
{
ehci_dbg
(
ehci
,
"iso request %p too long
\n
"
,
urb
);
status
=
-
EFBIG
;
goto
fail
;
}
if
((
stream
->
depth
+
sched
->
span
)
>
mod
)
{
ehci_dbg
(
ehci
,
"request %p would overflow (%d+%d>%d)
\n
"
,
urb
,
stream
->
depth
,
sched
->
span
,
mod
);
status
=
-
EFBIG
;
goto
fail
;
}
now
=
readl
(
&
ehci
->
regs
->
frame_index
)
%
mod
;
/* when's the last uframe this urb could start? */
max
=
now
+
mod
;
max
-=
itd_
sched
->
span
;
max
-=
sched
->
span
;
max
-=
8
*
SCHEDULE_SLOP
;
/* typical case: reuse current schedule. stream is still active,
* and no gaps from host falling behind (irq delays etc)
*/
if
(
likely
(
!
list_empty
(
&
stream
->
itd_list
)))
{
if
(
likely
(
!
list_empty
(
&
stream
->
td_list
)))
{
start
=
stream
->
next_uframe
;
if
(
start
<
now
)
start
+=
mod
;
if
(
likely
(
start
<
max
))
goto
ready
;
/* two cases:
* (a) we missed some uframes ... can reschedule
* (b) trying to overcommit the schedule
* FIXME (b) should be a hard failure
*/
/* else fell behind; try to reschedule */
}
/* need to schedule; when's the next (u)frame we could start?
...
...
@@ -864,47 +1058,41 @@ itd_stream_schedule (
* jump until after the queue is primed.
*/
start
=
SCHEDULE_SLOP
*
8
+
(
now
&
~
0x07
);
start
%=
mod
;
end
=
start
;
ehci_vdbg
(
ehci
,
"%s schedule from %d (%d..%d), was %d
\n
"
,
__FUNCTION__
,
now
,
start
,
max
,
stream
->
next_uframe
);
/* NOTE: assumes URB_ISO_ASAP, to limit complexity/bugs */
if
(
likely
(
max
>
(
start
+
urb
->
interval
)))
max
=
start
+
urb
->
interval
;
period
=
urb
->
interval
;
if
(
!
stream
->
highspeed
)
period
<<=
3
;
if
(
max
>
(
start
+
period
))
max
=
start
+
period
;
/* hack: account for itds already scheduled to this endpoint */
if
(
unlikely
(
list_empty
(
&
stream
->
itd_list
)
))
if
(
list_empty
(
&
stream
->
td_list
))
end
=
max
;
/* within [start..max] find a uframe slot with enough bandwidth */
end
%=
mod
;
do
{
unsigned
uframe
;
int
enough_space
=
1
;
int
enough_space
;
/* check schedule: enough space? */
uframe
=
start
;
do
{
uframe
%=
mod
;
/* can't commit more than 80% periodic == 100 usec */
if
(
periodic_usecs
(
ehci
,
uframe
>>
3
,
uframe
&
0x7
)
>
(
100
-
stream
->
usecs
))
{
enough_space
=
0
;
break
;
if
(
stream
->
highspeed
)
enough_space
=
itd_slot_ok
(
ehci
,
mod
,
start
,
end
,
stream
->
usecs
,
period
);
else
{
if
((
start
%
8
)
>=
6
)
continue
;
enough_space
=
sitd_slot_ok
(
ehci
,
mod
,
stream
,
start
,
end
,
sched
,
period
);
}
/* we know urb->interval is 2^N uframes */
uframe
+=
urb
->
interval
;
}
while
(
uframe
!=
end
);
/* (re)schedule it here if there's enough bandwidth */
if
(
enough_space
)
{
start
%=
mod
;
if
(
unlikely
(
!
list_empty
(
&
stream
->
i
td_list
)))
{
if
(
unlikely
(
!
list_empty
(
&
stream
->
td_list
)))
{
/* host fell behind ... maybe irq latencies
* delayed this request queue for too long.
*/
...
...
@@ -926,12 +1114,12 @@ itd_stream_schedule (
/* no room in the schedule */
ehci_dbg
(
ehci
,
"iso %ssched full %p (now %d end %d max %d)
\n
"
,
list_empty
(
&
stream
->
i
td_list
)
?
""
:
"re"
,
list_empty
(
&
stream
->
td_list
)
?
""
:
"re"
,
urb
,
now
,
end
,
max
);
status
=
-
ENOSPC
;
fail:
i
td_sched_free
(
stream
,
itd_
sched
);
i
so_sched_free
(
stream
,
sched
);
urb
->
hcpriv
=
0
;
return
status
;
...
...
@@ -961,13 +1149,13 @@ itd_init (struct ehci_iso_stream *stream, struct ehci_itd *itd)
static
inline
void
itd_patch
(
struct
ehci_itd
*
itd
,
struct
ehci_i
td_sched
*
itd
_sched
,
struct
ehci_i
so_sched
*
iso
_sched
,
unsigned
index
,
u16
uframe
,
int
first
)
{
struct
ehci_iso_
uframe
*
uf
=
&
itd
_sched
->
packet
[
index
];
struct
ehci_iso_
packet
*
uf
=
&
iso
_sched
->
packet
[
index
];
unsigned
pg
=
itd
->
pg
;
// BUG_ON (pg == 6 && uf->cross);
...
...
@@ -1012,12 +1200,12 @@ itd_link_urb (
{
int
packet
,
first
=
1
;
unsigned
next_uframe
,
uframe
,
frame
;
struct
ehci_i
td_sched
*
itd
_sched
=
urb
->
hcpriv
;
struct
ehci_i
so_sched
*
iso
_sched
=
urb
->
hcpriv
;
struct
ehci_itd
*
itd
;
next_uframe
=
stream
->
next_uframe
%
mod
;
if
(
unlikely
(
list_empty
(
&
stream
->
i
td_list
)))
{
if
(
unlikely
(
list_empty
(
&
stream
->
td_list
)))
{
hcd_to_bus
(
&
ehci
->
hcd
)
->
bandwidth_allocated
+=
stream
->
bandwidth
;
ehci_vdbg
(
ehci
,
...
...
@@ -1034,13 +1222,13 @@ itd_link_urb (
for
(
packet
=
0
,
itd
=
0
;
packet
<
urb
->
number_of_packets
;
)
{
if
(
itd
==
0
)
{
/* ASSERT: we have all necessary itds */
// BUG_ON (list_empty (&i
td_sched->i
td_list));
// BUG_ON (list_empty (&i
so_sched->
td_list));
/* ASSERT: no itds for this endpoint in this uframe */
itd
=
list_entry
(
i
td_sched
->
i
td_list
.
next
,
itd
=
list_entry
(
i
so_sched
->
td_list
.
next
,
struct
ehci_itd
,
itd_list
);
list_move_tail
(
&
itd
->
itd_list
,
&
stream
->
i
td_list
);
list_move_tail
(
&
itd
->
itd_list
,
&
stream
->
td_list
);
itd
->
stream
=
iso_stream_get
(
stream
);
itd
->
urb
=
usb_get_urb
(
urb
);
first
=
1
;
...
...
@@ -1051,10 +1239,11 @@ itd_link_urb (
frame
=
next_uframe
>>
3
;
itd
->
usecs
[
uframe
]
=
stream
->
usecs
;
itd_patch
(
itd
,
i
td
_sched
,
packet
,
uframe
,
first
);
itd_patch
(
itd
,
i
so
_sched
,
packet
,
uframe
,
first
);
first
=
0
;
next_uframe
+=
stream
->
interval
;
stream
->
depth
+=
stream
->
interval
;
next_uframe
%=
mod
;
packet
++
;
...
...
@@ -1068,7 +1257,7 @@ itd_link_urb (
stream
->
next_uframe
=
next_uframe
;
/* don't need that schedule data any more */
i
td_sched_free
(
stream
,
itd
_sched
);
i
so_sched_free
(
stream
,
iso
_sched
);
urb
->
hcpriv
=
0
;
if
(
unlikely
(
!
ehci
->
periodic_sched
++
))
...
...
@@ -1101,6 +1290,7 @@ itd_complete (
t
=
le32_to_cpup
(
&
itd
->
hw_transaction
[
uframe
]);
itd
->
hw_transaction
[
uframe
]
=
0
;
stream
->
depth
-=
stream
->
interval
;
/* report transfer status */
if
(
unlikely
(
t
&
ISO_ERRS
))
{
...
...
@@ -1126,7 +1316,7 @@ itd_complete (
usb_put_urb
(
urb
);
itd
->
urb
=
0
;
itd
->
stream
=
0
;
list_move
(
&
itd
->
itd_list
,
&
stream
->
free_
itd_
list
);
list_move
(
&
itd
->
itd_list
,
&
stream
->
free_list
);
iso_stream_put
(
ehci
,
stream
);
/* handle completion now? */
...
...
@@ -1134,7 +1324,7 @@ itd_complete (
return
0
;
/* ASSERT: it's really the last itd for this urb
list_for_each_entry (itd, &stream->
i
td_list, itd_list)
list_for_each_entry (itd, &stream->td_list, itd_list)
BUG_ON (itd->urb == urb);
*/
...
...
@@ -1149,7 +1339,7 @@ itd_complete (
(
void
)
disable_periodic
(
ehci
);
hcd_to_bus
(
&
ehci
->
hcd
)
->
bandwidth_isoc_reqs
--
;
if
(
unlikely
(
list_empty
(
&
stream
->
i
td_list
)))
{
if
(
unlikely
(
list_empty
(
&
stream
->
td_list
)))
{
hcd_to_bus
(
&
ehci
->
hcd
)
->
bandwidth_allocated
-=
stream
->
bandwidth
;
ehci_vdbg
(
ehci
,
...
...
@@ -1203,7 +1393,7 @@ static int itd_submit (struct ehci_hcd *ehci, struct urb *urb, int mem_flags)
/* schedule ... need to lock */
spin_lock_irqsave
(
&
ehci
->
lock
,
flags
);
status
=
i
td
_stream_schedule
(
ehci
,
urb
,
stream
);
status
=
i
so
_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
);
...
...
@@ -1233,7 +1423,7 @@ static void
scan_periodic
(
struct
ehci_hcd
*
ehci
,
struct
pt_regs
*
regs
)
{
unsigned
frame
,
clock
,
now_uframe
,
mod
;
unsigned
count
=
0
;
unsigned
modified
;
mod
=
ehci
->
periodic_size
<<
3
;
...
...
@@ -1244,47 +1434,50 @@ scan_periodic (struct ehci_hcd *ehci, struct pt_regs *regs)
*/
now_uframe
=
ehci
->
next_uframe
;
if
(
HCD_IS_RUNNING
(
ehci
->
hcd
.
state
))
clock
=
readl
(
&
ehci
->
regs
->
frame_index
)
%
mod
;
clock
=
readl
(
&
ehci
->
regs
->
frame_index
);
else
clock
=
now_uframe
+
mod
-
1
;
clock
%=
mod
;
for
(;;)
{
union
ehci_shadow
q
,
*
q_p
;
u32
type
,
*
hw_p
;
unsigned
uframes
;
/* don't scan past the live uframe */
frame
=
now_uframe
>>
3
;
restart:
/* scan schedule to _before_ current frame index */
if
((
frame
==
(
clock
>>
3
))
&&
HCD_IS_RUNNING
(
ehci
->
hcd
.
state
))
if
(
frame
==
(
clock
>>
3
))
uframes
=
now_uframe
&
0x07
;
else
else
{
/* safe to scan the whole frame at once */
now_uframe
|=
0x07
;
uframes
=
8
;
}
restart:
/* scan each element in frame's queue for completions */
q_p
=
&
ehci
->
pshadow
[
frame
];
hw_p
=
&
ehci
->
periodic
[
frame
];
q
.
ptr
=
q_p
->
ptr
;
type
=
Q_NEXT_TYPE
(
*
hw_p
);
modified
=
0
;
/* scan each element in frame's queue for completions */
while
(
q
.
ptr
!=
0
)
{
int
last
;
unsigned
uf
;
union
ehci_shadow
temp
;
switch
(
type
)
{
case
Q_TYPE_QH
:
last
=
(
q
.
qh
->
hw_next
==
EHCI_LIST_END
);
temp
=
q
.
qh
->
qh_next
;
/* handle any completions */
temp
.
qh
=
qh_get
(
q
.
qh
)
;
type
=
Q_NEXT_TYPE
(
q
.
qh
->
hw_next
);
count
+=
intr_complete
(
ehci
,
frame
,
qh_get
(
q
.
qh
),
regs
);
qh_put
(
ehci
,
q
.
qh
);
q
=
temp
;
q
=
q
.
qh
->
qh_next
;
modified
=
qh_completions
(
ehci
,
temp
.
qh
,
regs
);
if
(
unlikely
(
list_empty
(
&
temp
.
qh
->
qtd_list
)))
intr_deschedule
(
ehci
,
temp
.
qh
,
0
);
qh_put
(
ehci
,
temp
.
qh
);
break
;
case
Q_TYPE_FSTN
:
last
=
(
q
.
fstn
->
hw_next
==
EHCI_LIST_END
);
/* for "save place" FSTNs, look at QH entries
* in the previous frame for completions.
*/
...
...
@@ -1295,13 +1488,11 @@ scan_periodic (struct ehci_hcd *ehci, struct pt_regs *regs)
q
=
q
.
fstn
->
fstn_next
;
break
;
case
Q_TYPE_ITD
:
last
=
(
q
.
itd
->
hw_next
==
EHCI_LIST_END
);
/* skip itds for later in the frame */
rmb
();
for
(
uf
=
uframes
;
uf
<
8
;
uf
++
)
{
if
(
0
==
(
q
.
itd
->
hw_transaction
[
uf
]
&
I
SO
_ACTIVE
))
&
I
TD
_ACTIVE
))
continue
;
q_p
=
&
q
.
itd
->
itd_next
;
hw_p
=
&
q
.
itd
->
hw_next
;
...
...
@@ -1317,31 +1508,37 @@ scan_periodic (struct ehci_hcd *ehci, struct pt_regs *regs)
*/
*
q_p
=
q
.
itd
->
itd_next
;
*
hw_p
=
q
.
itd
->
hw_next
;
type
=
Q_NEXT_TYPE
(
q
.
itd
->
hw_next
);
wmb
();
/* always rescan here; simpler */
count
+=
itd_complete
(
ehci
,
q
.
itd
,
regs
);
goto
restart
;
modified
=
itd_complete
(
ehci
,
q
.
itd
,
regs
);
q
=
*
q_p
;
break
;
#ifdef have_split_iso
case
Q_TYPE_SITD
:
last
=
(
q
.
sitd
->
hw_next
==
EHCI_LIST_END
);
sitd_complete
(
ehci
,
q
.
sitd
);
if
(
q
.
sitd
->
hw_results
&
SITD_ACTIVE
)
{
q_p
=
&
q
.
sitd
->
sitd_next
;
hw_p
=
&
q
.
sitd
->
hw_next
;
type
=
Q_NEXT_TYPE
(
q
.
sitd
->
hw_next
);
// FIXME unlink SITD after split completes
q
=
q
.
sitd
->
sitd_next
;
q
=
*
q_p
;
break
;
}
*
q_p
=
q
.
sitd
->
sitd_next
;
*
hw_p
=
q
.
sitd
->
hw_next
;
type
=
Q_NEXT_TYPE
(
q
.
sitd
->
hw_next
);
wmb
();
modified
=
sitd_complete
(
ehci
,
q
.
sitd
,
regs
);
q
=
*
q_p
;
break
;
#endif
/* have_split_iso */
default:
dbg
(
"corrupt type %d frame %d shadow %p"
,
type
,
frame
,
q
.
ptr
);
// BUG ();
last
=
1
;
q
.
ptr
=
0
;
}
/*
did completion remove an interior q entry?
*/
if
(
unlikely
(
q
.
ptr
==
0
&&
!
last
))
/*
assume completion callbacks modify the queue
*/
if
(
unlikely
(
modified
))
goto
restart
;
}
...
...
@@ -1368,9 +1565,6 @@ scan_periodic (struct ehci_hcd *ehci, struct pt_regs *regs)
/* rescan the rest of this frame, then ... */
clock
=
now
;
}
else
{
/* FIXME sometimes we can scan the next frame
* right away, not always inching up on it ...
*/
now_uframe
++
;
now_uframe
%=
mod
;
}
...
...
drivers/usb/host/ehci.h
View file @
cdb7bc8f
...
...
@@ -74,11 +74,11 @@ struct ehci_hcd { /* one per controller */
struct
ehci_regs
*
regs
;
u32
hcs_params
;
/* cached register copy */
/* per-HC memory pools (could be per-
PCI-
bus, but ...) */
struct
pci
_pool
*
qh_pool
;
/* qh per active urb */
struct
pci
_pool
*
qtd_pool
;
/* one or more per qh */
struct
pci
_pool
*
itd_pool
;
/* itd per iso urb */
struct
pci
_pool
*
sitd_pool
;
/* sitd per split iso urb */
/* per-HC memory pools (could be per-bus, but ...) */
struct
dma
_pool
*
qh_pool
;
/* qh per active urb */
struct
dma
_pool
*
qtd_pool
;
/* one or more per qh */
struct
dma
_pool
*
itd_pool
;
/* itd per iso urb */
struct
dma
_pool
*
sitd_pool
;
/* sitd per split iso urb */
struct
timer_list
watchdog
;
struct
notifier_block
reboot_notifier
;
...
...
@@ -386,22 +386,24 @@ struct ehci_qh {
/*-------------------------------------------------------------------------*/
/* description of one iso
highspeed transaction (up to 3 KB data
) */
struct
ehci_iso_
uframe
{
/* description of one iso
transaction (up to 3 KB data if highspeed
) */
struct
ehci_iso_
packet
{
/* These will be copied to iTD when scheduling */
u64
bufp
;
/* itd->hw_bufp{,_hi}[pg] |= */
u32
transaction
;
/* itd->hw_transaction[i] |= */
u8
cross
;
/* buf crosses pages */
/* for full speed OUT splits */
u16
buf1
;
};
/* temporary schedule data for
highspeed packets from iso urbs
* each packet is one
uframe's usb transactions, in some itd
,
/* temporary schedule data for
packets from iso urbs (both speeds)
* each packet is one
logical usb transaction to the device (not TT)
,
* beginning at stream->next_uframe
*/
struct
ehci_i
td
_sched
{
struct
list_head
i
td_list
;
struct
ehci_i
so
_sched
{
struct
list_head
td_list
;
unsigned
span
;
struct
ehci_iso_
uframe
packet
[
0
];
struct
ehci_iso_
packet
packet
[
0
];
};
/*
...
...
@@ -415,22 +417,26 @@ struct ehci_iso_stream {
u32
refcount
;
u8
bEndpointAddress
;
struct
list_head
itd_list
;
/* queued itds */
struct
list_head
free_itd_list
;
/* list of unused itds */
struct
hcd_dev
*
dev
;
u8
highspeed
;
u16
depth
;
/* depth in uframes */
struct
list_head
td_list
;
/* queued itds/sitds */
struct
list_head
free_list
;
/* list of unused itds/sitds */
struct
usb_device
*
udev
;
/* output of (re)scheduling */
unsigned
long
start
;
/* jiffies */
unsigned
long
rescheduled
;
int
next_uframe
;
u32
splits
;
/* the rest is derived from the endpoint descriptor,
* trusting urb->interval ==
(1 << (epdesc->bInterval - 1)),
* trusting urb->interval ==
f(epdesc->bInterval) and
* including the extra info for hw_bufp[0..2]
*/
u8
interval
;
u8
usecs
;
u8
usecs
,
c_usecs
;
u16
maxp
;
u16
raw_mask
;
unsigned
bandwidth
;
/* This is used to initialize iTD's hw_bufp fields */
...
...
@@ -438,7 +444,8 @@ struct ehci_iso_stream {
u32
buf1
;
u32
buf2
;
/* ... sITD won't use buf[012], and needs TT access ... */
/* this is used to initialize sITD's tt info */
u32
address
;
};
/*-------------------------------------------------------------------------*/
...
...
@@ -460,7 +467,7 @@ struct ehci_itd {
#define EHCI_ITD_LENGTH(tok) (((tok)>>16) & 0x0fff)
#define EHCI_ITD_IOC (1 << 15)
/* interrupt on complete */
#define I
SO
_ACTIVE __constant_cpu_to_le32(EHCI_ISOC_ACTIVE)
#define I
TD
_ACTIVE __constant_cpu_to_le32(EHCI_ISOC_ACTIVE)
u32
hw_bufp
[
7
];
/* see EHCI 3.3.3 */
u32
hw_bufp_hi
[
7
];
/* Appendix B */
...
...
@@ -494,20 +501,33 @@ struct ehci_sitd {
/* uses bit field macros above - see EHCI 0.95 Table 3-8 */
u32
hw_fullspeed_ep
;
/* see EHCI table 3-9 */
u32
hw_uframe
;
/* see EHCI table 3-10 */
u32
hw_tx_results1
;
/* see EHCI table 3-11 */
u32
hw_tx_results2
;
/* see EHCI table 3-12 */
u32
hw_tx_results3
;
/* see EHCI table 3-12 */
u32
hw_results
;
/* see EHCI table 3-11 */
#define SITD_IOC (1 << 31)
/* interrupt on completion */
#define SITD_PAGE (1 << 30)
/* buffer 0/1 */
#define SITD_LENGTH(x) (0x3ff & ((x)>>16))
#define SITD_STS_ACTIVE (1 << 7)
/* HC may execute this */
#define SITD_STS_ERR (1 << 6)
/* error from TT */
#define SITD_STS_DBE (1 << 5)
/* data buffer error (in HC) */
#define SITD_STS_BABBLE (1 << 4)
/* device was babbling */
#define SITD_STS_XACT (1 << 3)
/* illegal IN response */
#define SITD_STS_MMF (1 << 2)
/* incomplete split transaction */
#define SITD_STS_STS (1 << 1)
/* split transaction state */
#define SITD_ACTIVE __constant_cpu_to_le32(SITD_STS_ACTIVE)
u32
hw_buf
[
2
];
/* see EHCI table 3-12 */
u32
hw_backpointer
;
/* see EHCI table 3-13 */
u32
hw_buf_hi
[
2
];
/* Appendix B */
/* the rest is HCD-private */
dma_addr_t
sitd_dma
;
union
ehci_shadow
sitd_next
;
/* ptr to periodic q entry */
struct
urb
*
urb
;
dma_addr_t
buf_dma
;
/* buffer address */
unsigned
short
usecs
;
/* start bandwidth */
unsigned
short
c_usecs
;
/* completion bandwidth */
struct
urb
*
urb
;
struct
ehci_iso_stream
*
stream
;
/* endpoint's queue */
struct
list_head
sitd_list
;
/* list of stream's sitds */
unsigned
frame
;
unsigned
index
;
}
__attribute__
((
aligned
(
32
)));
/*-------------------------------------------------------------------------*/
...
...
drivers/usb/host/ohci-hcd.c
View file @
cdb7bc8f
...
...
@@ -17,6 +17,7 @@
*
* History:
*
* 2004/02/04 use generic dma_* functions instead of pci_* (dsaxena@plexity.net)
* 2003/02/24 show registers in sysfs (Kevin Brosius)
*
* 2002/09/03 get rid of ed hashtables, rework periodic scheduling and
...
...
@@ -96,6 +97,8 @@
#include <linux/interrupt.h>
/* for in_interrupt () */
#include <linux/usb.h>
#include "../core/hcd.h"
#include <linux/dma-mapping.h>
#include <linux/dmapool.h>
/* needed by ohci-mem.c when no PCI */
#include <asm/io.h>
#include <asm/irq.h>
...
...
@@ -642,7 +645,8 @@ static void ohci_stop (struct usb_hcd *hcd)
remove_debug_files
(
ohci
);
ohci_mem_cleanup
(
ohci
);
if
(
ohci
->
hcca
)
{
pci_free_consistent
(
ohci
->
hcd
.
pdev
,
sizeof
*
ohci
->
hcca
,
dma_free_coherent
(
ohci
->
hcd
.
self
.
controller
,
sizeof
*
ohci
->
hcca
,
ohci
->
hcca
,
ohci
->
hcca_dma
);
ohci
->
hcca
=
NULL
;
ohci
->
hcca_dma
=
0
;
...
...
drivers/usb/host/ohci-mem.c
View file @
cdb7bc8f
...
...
@@ -13,7 +13,7 @@
* There's basically three types of memory:
* - data used only by the HCD ... kmalloc is fine
* - async and periodic schedules, shared by HC and HCD ... these
* need to use
pci_pool or pci_alloc_consist
ent
* need to use
dma_pool or dma_alloc_coher
ent
* - driver buffers, read/written by HC ... the hcd glue or the
* device driver provides us with dma addresses
*
...
...
@@ -45,18 +45,18 @@ static void ohci_hcd_free (struct usb_hcd *hcd)
static
int
ohci_mem_init
(
struct
ohci_hcd
*
ohci
)
{
ohci
->
td_cache
=
pci_pool_create
(
"ohci_td"
,
ohci
->
hcd
.
pdev
,
ohci
->
td_cache
=
dma_pool_create
(
"ohci_td"
,
ohci
->
hcd
.
self
.
controller
,
sizeof
(
struct
td
),
32
/* byte alignment */
,
0
/* no page-crossing issues */
);
if
(
!
ohci
->
td_cache
)
return
-
ENOMEM
;
ohci
->
ed_cache
=
pci_pool_create
(
"ohci_ed"
,
ohci
->
hcd
.
pdev
,
ohci
->
ed_cache
=
dma_pool_create
(
"ohci_ed"
,
ohci
->
hcd
.
self
.
controller
,
sizeof
(
struct
ed
),
16
/* byte alignment */
,
0
/* no page-crossing issues */
);
if
(
!
ohci
->
ed_cache
)
{
pci
_pool_destroy
(
ohci
->
td_cache
);
dma
_pool_destroy
(
ohci
->
td_cache
);
return
-
ENOMEM
;
}
return
0
;
...
...
@@ -65,11 +65,11 @@ static int ohci_mem_init (struct ohci_hcd *ohci)
static
void
ohci_mem_cleanup
(
struct
ohci_hcd
*
ohci
)
{
if
(
ohci
->
td_cache
)
{
pci
_pool_destroy
(
ohci
->
td_cache
);
dma
_pool_destroy
(
ohci
->
td_cache
);
ohci
->
td_cache
=
0
;
}
if
(
ohci
->
ed_cache
)
{
pci
_pool_destroy
(
ohci
->
ed_cache
);
dma
_pool_destroy
(
ohci
->
ed_cache
);
ohci
->
ed_cache
=
0
;
}
}
...
...
@@ -96,7 +96,7 @@ td_alloc (struct ohci_hcd *hc, int mem_flags)
dma_addr_t
dma
;
struct
td
*
td
;
td
=
pci
_pool_alloc
(
hc
->
td_cache
,
mem_flags
,
&
dma
);
td
=
dma
_pool_alloc
(
hc
->
td_cache
,
mem_flags
,
&
dma
);
if
(
td
)
{
/* in case hc fetches it, make it look dead */
memset
(
td
,
0
,
sizeof
*
td
);
...
...
@@ -118,7 +118,7 @@ td_free (struct ohci_hcd *hc, struct td *td)
*
prev
=
td
->
td_hash
;
else
if
((
td
->
hwINFO
&
TD_DONE
)
!=
0
)
ohci_dbg
(
hc
,
"no hash for td %p
\n
"
,
td
);
pci
_pool_free
(
hc
->
td_cache
,
td
,
td
->
td_dma
);
dma
_pool_free
(
hc
->
td_cache
,
td
,
td
->
td_dma
);
}
/*-------------------------------------------------------------------------*/
...
...
@@ -130,7 +130,7 @@ ed_alloc (struct ohci_hcd *hc, int mem_flags)
dma_addr_t
dma
;
struct
ed
*
ed
;
ed
=
pci
_pool_alloc
(
hc
->
ed_cache
,
mem_flags
,
&
dma
);
ed
=
dma
_pool_alloc
(
hc
->
ed_cache
,
mem_flags
,
&
dma
);
if
(
ed
)
{
memset
(
ed
,
0
,
sizeof
(
*
ed
));
INIT_LIST_HEAD
(
&
ed
->
td_list
);
...
...
@@ -142,6 +142,6 @@ ed_alloc (struct ohci_hcd *hc, int mem_flags)
static
void
ed_free
(
struct
ohci_hcd
*
hc
,
struct
ed
*
ed
)
{
pci
_pool_free
(
hc
->
ed_cache
,
ed
,
ed
->
dma
);
dma
_pool_free
(
hc
->
ed_cache
,
ed
,
ed
->
dma
);
}
drivers/usb/host/ohci-omap.c
View file @
cdb7bc8f
...
...
@@ -388,9 +388,7 @@ int usb_hcd_omap_probe (const struct hc_driver *driver,
hcd
->
description
=
driver
->
description
;
hcd
->
irq
=
dev
->
irq
[
0
];
hcd
->
regs
=
dev
->
mapbase
;
hcd
->
pdev
=
OMAP_FAKE_PCIDEV
;
hcd
->
self
.
controller
=
&
dev
->
dev
;
hcd
->
controller
=
hcd
->
self
.
controller
;
retval
=
hcd_buffer_create
(
hcd
);
if
(
retval
!=
0
)
{
...
...
@@ -494,12 +492,10 @@ ohci_omap_start (struct usb_hcd *hcd)
struct
ohci_hcd
*
ohci
=
hcd_to_ohci
(
hcd
);
int
ret
;
if
(
hcd
->
pdev
)
{
ohci
->
hcca
=
pci_alloc_consistent
(
hcd
->
pdev
,
ohci
->
hcca
=
dma_alloc_consistent
(
hcd
->
self
.
controller
,
sizeof
*
ohci
->
hcca
,
&
ohci
->
hcca_dma
);
if
(
!
ohci
->
hcca
)
return
-
ENOMEM
;
}
memset
(
ohci
->
hcca
,
0
,
sizeof
(
struct
ohci_hcca
));
if
((
ret
=
ohci_mem_init
(
ohci
))
<
0
)
{
...
...
drivers/usb/host/ohci-pci.c
View file @
cdb7bc8f
...
...
@@ -45,17 +45,19 @@ ohci_pci_start (struct usb_hcd *hcd)
struct
ohci_hcd
*
ohci
=
hcd_to_ohci
(
hcd
);
int
ret
;
if
(
hcd
->
pdev
)
{
ohci
->
hcca
=
pci_alloc_consistent
(
hcd
->
pdev
,
sizeof
*
ohci
->
hcca
,
&
ohci
->
hcca_dma
);
ohci
->
hcca
=
dma_alloc_coherent
(
hcd
->
self
.
controller
,
sizeof
*
ohci
->
hcca
,
&
ohci
->
hcca_dma
,
0
);
if
(
!
ohci
->
hcca
)
return
-
ENOMEM
;
if
(
hcd
->
self
.
controller
&&
hcd
->
self
.
controller
->
bus
==
&
pci_bus_type
)
{
struct
pci_dev
*
pdev
=
to_pci_dev
(
hcd
->
self
.
controller
);
/* AMD 756, for most chips (early revs), corrupts register
* values on read ... so enable the vendor workaround.
*/
if
(
hcd
->
pdev
->
vendor
==
PCI_VENDOR_ID_AMD
&&
hcd
->
pdev
->
device
==
0x740c
)
{
if
(
pdev
->
vendor
==
PCI_VENDOR_ID_AMD
&&
pdev
->
device
==
0x740c
)
{
ohci
->
flags
=
OHCI_QUIRK_AMD756
;
ohci_info
(
ohci
,
"AMD756 erratum 4 workaround
\n
"
);
}
...
...
@@ -68,8 +70,8 @@ ohci_pci_start (struct usb_hcd *hcd)
* for this chip. Evidently control and bulk lists
* can get confused. (B&W G3 models, and ...)
*/
else
if
(
hcd
->
pdev
->
vendor
==
PCI_VENDOR_ID_OPTI
&&
hcd
->
pdev
->
device
==
0xc861
)
{
else
if
(
pdev
->
vendor
==
PCI_VENDOR_ID_OPTI
&&
pdev
->
device
==
0xc861
)
{
ohci_info
(
ohci
,
"WARNING: OPTi workarounds unavailable
\n
"
);
}
...
...
@@ -78,12 +80,11 @@ ohci_pci_start (struct usb_hcd *hcd)
* identify the USB (fn2). This quirk might apply to more or
* even all NSC stuff.
*/
else
if
(
hcd
->
pdev
->
vendor
==
PCI_VENDOR_ID_NS
)
{
struct
pci_dev
*
b
,
*
hc
;
else
if
(
pdev
->
vendor
==
PCI_VENDOR_ID_NS
)
{
struct
pci_dev
*
b
;
hc
=
hcd
->
pdev
;
b
=
pci_find_slot
(
hc
->
bus
->
number
,
PCI_DEVFN
(
PCI_SLOT
(
hc
->
devfn
),
1
));
b
=
pci_find_slot
(
pdev
->
bus
->
number
,
PCI_DEVFN
(
PCI_SLOT
(
pdev
->
devfn
),
1
));
if
(
b
&&
b
->
device
==
PCI_DEVICE_ID_NS_87560_LIO
&&
b
->
vendor
==
PCI_VENDOR_ID_NS
)
{
ohci
->
flags
|=
OHCI_QUIRK_SUPERIO
;
...
...
@@ -145,7 +146,7 @@ static int ohci_pci_suspend (struct usb_hcd *hcd, u32 state)
#ifdef CONFIG_PMAC_PBOOK
if
(
_machine
==
_MACH_Pmac
)
disable_irq
(
hcd
->
pdev
->
irq
);
disable_irq
(
(
to_pci_dev
(
hcd
->
self
.
controller
))
->
irq
);
/* else, 2.4 assumes shared irqs -- don't disable */
#endif
...
...
@@ -179,15 +180,17 @@ static int ohci_pci_suspend (struct usb_hcd *hcd, u32 state)
* memory during sleep. We disable its bus master bit during
* suspend
*/
pci_read_config_word
(
hcd
->
pdev
,
PCI_COMMAND
,
&
cmd
);
pci_read_config_word
(
to_pci_dev
(
hcd
->
self
.
controller
),
PCI_COMMAND
,
&
cmd
);
cmd
&=
~
PCI_COMMAND_MASTER
;
pci_write_config_word
(
hcd
->
pdev
,
PCI_COMMAND
,
cmd
);
pci_write_config_word
(
to_pci_dev
(
hcd
->
self
.
controller
),
PCI_COMMAND
,
cmd
);
#ifdef CONFIG_PMAC_PBOOK
{
struct
device_node
*
of_node
;
/* Disable USB PAD & cell clock */
of_node
=
pci_device_to_OF_node
(
hcd
->
pdev
);
of_node
=
pci_device_to_OF_node
(
to_pci_dev
(
hcd
->
self
.
controller
)
);
if
(
of_node
)
pmac_call_feature
(
PMAC_FTR_USB_ENABLE
,
of_node
,
0
,
0
);
}
...
...
@@ -207,7 +210,7 @@ static int ohci_pci_resume (struct usb_hcd *hcd)
struct
device_node
*
of_node
;
/* Re-enable USB PAD & cell clock */
of_node
=
pci_device_to_OF_node
(
hcd
->
pdev
);
of_node
=
pci_device_to_OF_node
(
to_pci_dev
(
hcd
->
self
.
controller
)
);
if
(
of_node
)
pmac_call_feature
(
PMAC_FTR_USB_ENABLE
,
of_node
,
0
,
1
);
}
...
...
@@ -222,7 +225,7 @@ static int ohci_pci_resume (struct usb_hcd *hcd)
#endif
/* Re-enable bus mastering */
pci_set_master
(
ohci
->
hcd
.
pdev
);
pci_set_master
(
to_pci_dev
(
ohci
->
hcd
.
self
.
controller
)
);
switch
(
temp
)
{
...
...
@@ -282,7 +285,7 @@ static int ohci_pci_resume (struct usb_hcd *hcd)
#ifdef CONFIG_PMAC_PBOOK
if
(
_machine
==
_MACH_Pmac
)
enable_irq
(
hcd
->
pdev
->
irq
);
enable_irq
(
to_pci_dev
(
hcd
->
self
.
controller
)
->
irq
);
#endif
/* Check for a pending done list */
...
...
drivers/usb/host/ohci-q.c
View file @
cdb7bc8f
...
...
@@ -375,7 +375,7 @@ static struct ed *ed_get (
if
(
!
(
ed
=
dev
->
ep
[
ep
]))
{
struct
td
*
td
;
ed
=
ed_alloc
(
ohci
,
SLAB
_ATOMIC
);
ed
=
ed_alloc
(
ohci
,
GFP
_ATOMIC
);
if
(
!
ed
)
{
/* out of memory */
goto
done
;
...
...
@@ -383,7 +383,7 @@ static struct ed *ed_get (
dev
->
ep
[
ep
]
=
ed
;
/* dummy td; end of td list for ed */
td
=
td_alloc
(
ohci
,
SLAB
_ATOMIC
);
td
=
td_alloc
(
ohci
,
GFP
_ATOMIC
);
if
(
!
td
)
{
/* out of memory */
ed_free
(
ohci
,
ed
);
...
...
drivers/usb/host/ohci-sa1111.c
View file @
cdb7bc8f
...
...
@@ -167,9 +167,7 @@ int usb_hcd_sa1111_probe (const struct hc_driver *driver,
hcd
->
description
=
driver
->
description
;
hcd
->
irq
=
dev
->
irq
[
1
];
hcd
->
regs
=
dev
->
mapbase
;
hcd
->
pdev
=
SA1111_FAKE_PCIDEV
;
hcd
->
self
.
controller
=
&
dev
->
dev
;
hcd
->
controller
=
hcd
->
self
.
controller
;
retval
=
hcd_buffer_create
(
hcd
);
if
(
retval
!=
0
)
{
...
...
@@ -270,12 +268,10 @@ ohci_sa1111_start (struct usb_hcd *hcd)
struct
ohci_hcd
*
ohci
=
hcd_to_ohci
(
hcd
);
int
ret
;
if
(
hcd
->
pdev
)
{
ohci
->
hcca
=
pci_alloc_consistent
(
hcd
->
pdev
,
sizeof
*
ohci
->
hcca
,
&
ohci
->
hcca_dma
);
ohci
->
hcca
=
dma_alloc_coherent
(
hcd
->
self
.
controller
,
sizeof
*
ohci
->
hcca
,
&
ohci
->
hcca_dma
,
0
);
if
(
!
ohci
->
hcca
)
return
-
ENOMEM
;
}
memset
(
ohci
->
hcca
,
0
,
sizeof
(
struct
ohci_hcca
));
if
((
ret
=
ohci_mem_init
(
ohci
))
<
0
)
{
...
...
drivers/usb/host/ohci.h
View file @
cdb7bc8f
...
...
@@ -361,8 +361,8 @@ struct ohci_hcd {
/*
* memory management for queue data structures
*/
struct
pci
_pool
*
td_cache
;
struct
pci
_pool
*
ed_cache
;
struct
dma
_pool
*
td_cache
;
struct
dma
_pool
*
ed_cache
;
struct
td
*
td_hash
[
TD_HASH_SIZE
];
/*
...
...
@@ -391,13 +391,13 @@ struct ohci_hcd {
#endif
/* DEBUG */
#define ohci_dbg(ohci, fmt, args...) \
dev_dbg ((ohci)->hcd.controller , fmt , ## args )
dev_dbg ((ohci)->hcd.
self.
controller , fmt , ## args )
#define ohci_err(ohci, fmt, args...) \
dev_err ((ohci)->hcd.controller , fmt , ## args )
dev_err ((ohci)->hcd.
self.
controller , fmt , ## args )
#define ohci_info(ohci, fmt, args...) \
dev_info ((ohci)->hcd.controller , fmt , ## args )
dev_info ((ohci)->hcd.
self.
controller , fmt , ## args )
#define ohci_warn(ohci, fmt, args...) \
dev_warn ((ohci)->hcd.controller , fmt , ## args )
dev_warn ((ohci)->hcd.
self.
controller , fmt , ## args )
#ifdef OHCI_VERBOSE_DEBUG
# define ohci_vdbg ohci_dbg
...
...
drivers/usb/host/uhci-debug.c
View file @
cdb7bc8f
...
...
@@ -225,20 +225,22 @@ static int uhci_show_sc(int port, unsigned short status, char *buf, int len)
char
*
out
=
buf
;
/* Try to make sure there's enough memory */
if
(
len
<
8
0
)
if
(
len
<
16
0
)
return
0
;
out
+=
sprintf
(
out
,
" stat%d = %04x
%s%s%s%s%s%s%s%s
\n
"
,
out
+=
sprintf
(
out
,
" stat%d = %04x
%s%s
%s%s%s%s%s%s%s%s
\n
"
,
port
,
status
,
(
status
&
USBPORTSC_SUSP
)
?
"PortSuspend "
:
""
,
(
status
&
USBPORTSC_PR
)
?
"PortReset "
:
""
,
(
status
&
USBPORTSC_LSDA
)
?
"LowSpeed "
:
""
,
(
status
&
USBPORTSC_RD
)
?
"ResumeDetect "
:
""
,
(
status
&
USBPORTSC_PEC
)
?
"EnableChange "
:
""
,
(
status
&
USBPORTSC_PE
)
?
"PortEnabled "
:
""
,
(
status
&
USBPORTSC_CSC
)
?
"ConnectChange "
:
""
,
(
status
&
USBPORTSC_CCS
)
?
"PortConnected "
:
""
);
(
status
&
USBPORTSC_SUSP
)
?
" Suspend"
:
""
,
(
status
&
USBPORTSC_OCC
)
?
" OverCurrentChange"
:
""
,
(
status
&
USBPORTSC_OC
)
?
" OverCurrent"
:
""
,
(
status
&
USBPORTSC_PR
)
?
" Reset"
:
""
,
(
status
&
USBPORTSC_LSDA
)
?
" LowSpeed"
:
""
,
(
status
&
USBPORTSC_RD
)
?
" ResumeDetect"
:
""
,
(
status
&
USBPORTSC_PEC
)
?
" EnableChange"
:
""
,
(
status
&
USBPORTSC_PE
)
?
" Enabled"
:
""
,
(
status
&
USBPORTSC_CSC
)
?
" ConnectChange"
:
""
,
(
status
&
USBPORTSC_CCS
)
?
" Connected"
:
""
);
return
out
-
buf
;
}
...
...
@@ -321,8 +323,8 @@ static int uhci_show_urbp(struct uhci_hcd *uhci, struct urb_priv *urbp, char *bu
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
);
if
(
urbp
->
urb
->
status
!=
-
EINPROGRESS
)
out
+=
sprintf
(
out
,
"Status=%d "
,
urbp
->
urb
->
status
);
//out += sprintf(out, "Inserttime=%lx ",urbp->inserttime);
//out += sprintf(out, "FSBRtime=%lx ",urbp->fsbrtime);
...
...
@@ -402,7 +404,7 @@ static int uhci_show_lists(struct uhci_hcd *uhci, char *buf, int len)
head
=
&
uhci
->
complete_list
;
tmp
=
head
->
next
;
while
(
tmp
!=
head
)
{
struct
urb_priv
*
urbp
=
list_entry
(
tmp
,
struct
urb_priv
,
complete
_list
);
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
));
...
...
@@ -418,7 +420,7 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
{
unsigned
long
flags
;
char
*
out
=
buf
;
int
i
;
int
i
,
j
;
struct
uhci_qh
*
qh
;
struct
uhci_td
*
td
;
struct
list_head
*
tmp
,
*
head
;
...
...
@@ -473,10 +475,11 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
continue
;
}
j
=
(
i
<
7
)
?
7
:
i
+
1
;
/* Next skeleton */
if
(
list_empty
(
&
qh
->
list
))
{
if
(
i
<
UHCI_NUM_SKELQH
-
1
)
{
if
(
qh
->
link
!=
(
cpu_to_le32
(
uhci
->
skelqh
[
i
+
1
]
->
dma_handle
)
|
UHCI_PTR_QH
))
{
(
cpu_to_le32
(
uhci
->
skelqh
[
j
]
->
dma_handle
)
|
UHCI_PTR_QH
))
{
show_qh_name
();
out
+=
sprintf
(
out
,
" skeleton QH not linked to next skeleton QH!
\n
"
);
}
...
...
@@ -500,7 +503,7 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
if
(
i
<
UHCI_NUM_SKELQH
-
1
)
{
if
(
qh
->
link
!=
(
cpu_to_le32
(
uhci
->
skelqh
[
i
+
1
]
->
dma_handle
)
|
UHCI_PTR_QH
))
(
cpu_to_le32
(
uhci
->
skelqh
[
j
]
->
dma_handle
)
|
UHCI_PTR_QH
))
out
+=
sprintf
(
out
,
" last QH not linked to next skeleton!
\n
"
);
}
}
...
...
drivers/usb/host/uhci-hcd.c
View file @
cdb7bc8f
...
...
@@ -13,6 +13,7 @@
* (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface
* support from usb-ohci.c by Adam Richter, adam@yggdrasil.com).
* (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c)
* (C) Copyright 2004 Alan Stern, stern@rowland.harvard.edu
*
* Intel documents this fairly well, and as far as I know there
* are no royalties or anything like that, but even so there are
...
...
@@ -27,6 +28,11 @@
*/
#include <linux/config.h>
#ifdef CONFIG_USB_DEBUG
#define DEBUG
#else
#undef DEBUG
#endif
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/kernel.h>
...
...
@@ -41,13 +47,12 @@
#include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <linux/proc_fs.h>
#ifdef CONFIG_USB_DEBUG
#define DEBUG
#else
#undef DEBUG
#endif
#include <linux/pm.h>
#include <linux/dmapool.h>
#include <linux/dma-mapping.h>
#include <linux/usb.h>
#include <asm/bitops.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/irq.h>
...
...
@@ -56,13 +61,13 @@
#include "../core/hcd.h"
#include "uhci-hcd.h"
#include <linux/pm.h>
/*
* Version Information
*/
#define DRIVER_VERSION "v2.1"
#define DRIVER_AUTHOR "Linus 'Frodo Rabbit' Torvalds, Johannes Erdfelt, Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber"
#define DRIVER_VERSION "v2.2"
#define DRIVER_AUTHOR "Linus 'Frodo Rabbit' Torvalds, Johannes Erdfelt, \
Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber, \
Alan Stern"
#define DRIVER_DESC "USB Universal Host Controller Interface driver"
/*
...
...
@@ -80,7 +85,7 @@ static int debug = 0;
MODULE_PARM
(
debug
,
"i"
);
MODULE_PARM_DESC
(
debug
,
"Debug level"
);
static
char
*
errbuf
;
#define ERRBUF_LEN (
PAGE_SIZE * 8
)
#define ERRBUF_LEN (
32 * 1024
)
#include "uhci-hub.c"
#include "uhci-debug.c"
...
...
@@ -121,21 +126,17 @@ static inline void uhci_set_next_interrupt(struct uhci_hcd *uhci)
static
inline
void
uhci_clear_next_interrupt
(
struct
uhci_hcd
*
uhci
)
{
unsigned
long
flags
;
spin_lock_irqsave
(
&
uhci
->
frame_list_lock
,
flags
);
spin_lock
(
&
uhci
->
frame_list_lock
);
uhci
->
term_td
->
status
&=
~
cpu_to_le32
(
TD_CTRL_IOC
);
spin_unlock
_irqrestore
(
&
uhci
->
frame_list_lock
,
flags
);
spin_unlock
(
&
uhci
->
frame_list_lock
);
}
static
inline
void
uhci_add_complete
(
struct
uhci_hcd
*
uhci
,
struct
urb
*
urb
)
static
inline
void
uhci_moveto_complete
(
struct
uhci_hcd
*
uhci
,
struct
urb_priv
*
urbp
)
{
struct
urb_priv
*
urbp
=
(
struct
urb_priv
*
)
urb
->
hcpriv
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
uhci
->
complete_list_lock
,
flags
);
list_add_tail
(
&
urbp
->
complete_list
,
&
uhci
->
complete_list
);
spin_unlock_irqrestore
(
&
uhci
->
complete_list_lock
,
flags
);
spin_lock
(
&
uhci
->
complete_list_lock
);
list_move_tail
(
&
urbp
->
urb_list
,
&
uhci
->
complete_list
);
spin_unlock
(
&
uhci
->
complete_list_lock
);
}
static
struct
uhci_td
*
uhci_alloc_td
(
struct
uhci_hcd
*
uhci
,
struct
usb_device
*
dev
)
...
...
@@ -143,7 +144,7 @@ static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci, struct usb_device *d
dma_addr_t
dma_handle
;
struct
uhci_td
*
td
;
td
=
pci
_pool_alloc
(
uhci
->
td_pool
,
GFP_ATOMIC
,
&
dma_handle
);
td
=
dma
_pool_alloc
(
uhci
->
td_pool
,
GFP_ATOMIC
,
&
dma_handle
);
if
(
!
td
)
return
NULL
;
...
...
@@ -286,16 +287,16 @@ static void uhci_insert_tds_in_qh(struct uhci_qh *qh, struct urb *urb, u32 bread
static
void
uhci_free_td
(
struct
uhci_hcd
*
uhci
,
struct
uhci_td
*
td
)
{
if
(
!
list_empty
(
&
td
->
list
))
d
bg
(
"td %p is still in list!
"
,
td
);
d
ev_warn
(
uhci_dev
(
uhci
),
"td %p still in list!
\n
"
,
td
);
if
(
!
list_empty
(
&
td
->
remove_list
))
d
bg
(
"td %p still in remove_list!
"
,
td
);
d
ev_warn
(
uhci_dev
(
uhci
),
"td %p still in remove_list!
\n
"
,
td
);
if
(
!
list_empty
(
&
td
->
fl_list
))
d
bg
(
"td %p is still in fl_list!
"
,
td
);
d
ev_warn
(
uhci_dev
(
uhci
),
"td %p still in fl_list!
\n
"
,
td
);
if
(
td
->
dev
)
usb_put_dev
(
td
->
dev
);
pci
_pool_free
(
uhci
->
td_pool
,
td
,
td
->
dma_handle
);
dma
_pool_free
(
uhci
->
td_pool
,
td
,
td
->
dma_handle
);
}
static
struct
uhci_qh
*
uhci_alloc_qh
(
struct
uhci_hcd
*
uhci
,
struct
usb_device
*
dev
)
...
...
@@ -303,7 +304,7 @@ static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci, struct usb_device *d
dma_addr_t
dma_handle
;
struct
uhci_qh
*
qh
;
qh
=
pci
_pool_alloc
(
uhci
->
qh_pool
,
GFP_ATOMIC
,
&
dma_handle
);
qh
=
dma
_pool_alloc
(
uhci
->
qh_pool
,
GFP_ATOMIC
,
&
dma_handle
);
if
(
!
qh
)
return
NULL
;
...
...
@@ -326,14 +327,14 @@ static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci, struct usb_device *d
static
void
uhci_free_qh
(
struct
uhci_hcd
*
uhci
,
struct
uhci_qh
*
qh
)
{
if
(
!
list_empty
(
&
qh
->
list
))
d
bg
(
"qh %p list not empty!
"
,
qh
);
d
ev_warn
(
uhci_dev
(
uhci
),
"qh %p list not empty!
\n
"
,
qh
);
if
(
!
list_empty
(
&
qh
->
remove_list
))
d
bg
(
"qh %p still in remove_list!
"
,
qh
);
d
ev_warn
(
uhci_dev
(
uhci
),
"qh %p still in remove_list!
\n
"
,
qh
);
if
(
qh
->
dev
)
usb_put_dev
(
qh
->
dev
);
pci
_pool_free
(
uhci
->
qh_pool
,
qh
,
qh
->
dma_handle
);
dma
_pool_free
(
uhci
->
qh_pool
,
qh
,
qh
->
dma_handle
);
}
/*
...
...
@@ -658,10 +659,8 @@ static struct urb_priv *uhci_alloc_urb_priv(struct uhci_hcd *uhci, struct urb *u
struct
urb_priv
*
urbp
;
urbp
=
kmem_cache_alloc
(
uhci_up_cachep
,
SLAB_ATOMIC
);
if
(
!
urbp
)
{
err
(
"uhci_alloc_urb_priv: couldn't allocate memory for urb_priv
\n
"
);
if
(
!
urbp
)
return
NULL
;
}
memset
((
void
*
)
urbp
,
0
,
sizeof
(
*
urbp
));
...
...
@@ -671,7 +670,6 @@ static struct urb_priv *uhci_alloc_urb_priv(struct uhci_hcd *uhci, struct urb *u
INIT_LIST_HEAD
(
&
urbp
->
td_list
);
INIT_LIST_HEAD
(
&
urbp
->
queue_list
);
INIT_LIST_HEAD
(
&
urbp
->
complete_list
);
INIT_LIST_HEAD
(
&
urbp
->
urb_list
);
list_add_tail
(
&
urbp
->
urb_list
,
&
uhci
->
urb_list
);
...
...
@@ -720,10 +718,8 @@ static void uhci_destroy_urb_priv(struct uhci_hcd *uhci, struct urb *urb)
return
;
if
(
!
list_empty
(
&
urbp
->
urb_list
))
warn
(
"uhci_destroy_urb_priv: urb %p still on uhci->urb_list or uhci->remove_list"
,
urb
);
if
(
!
list_empty
(
&
urbp
->
complete_list
))
warn
(
"uhci_destroy_urb_priv: urb %p still on uhci->complete_list"
,
urb
);
dev_warn
(
uhci_dev
(
uhci
),
"urb %p still on uhci->urb_list "
"or uhci->remove_list!
\n
"
,
urb
);
spin_lock_irqsave
(
&
uhci
->
td_remove_list_lock
,
flags
);
...
...
@@ -913,7 +909,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur
uhci_insert_tds_in_qh
(
qh
,
urb
,
UHCI_PTR_BREADTH
);
/* Low
speed transfers get a different queue, and won't hog the bus */
/* 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
{
...
...
@@ -961,17 +957,15 @@ static int usb_control_retrigger_status(struct uhci_hcd *uhci, struct urb *urb)
}
urbp
->
qh
=
uhci_alloc_qh
(
uhci
,
urb
->
dev
);
if
(
!
urbp
->
qh
)
{
err
(
"unable to allocate new QH for control retrigger"
);
if
(
!
urbp
->
qh
)
return
-
ENOMEM
;
}
urbp
->
qh
->
urbp
=
urbp
;
/* One TD, who cares about Breadth first? */
uhci_insert_tds_in_qh
(
urbp
->
qh
,
urb
,
UHCI_PTR_DEPTH
);
/* Low
speed transfers get a different queue */
/* Low
-
speed transfers get a different queue */
if
(
urb
->
dev
->
speed
==
USB_SPEED_LOW
)
uhci_insert_qh
(
uhci
,
uhci
->
skel_ls_control_qh
,
urb
);
else
...
...
@@ -1073,7 +1067,8 @@ static int uhci_result_control(struct uhci_hcd *uhci, struct urb *urb)
err:
if
((
debug
==
1
&&
ret
!=
-
EPIPE
)
||
debug
>
1
)
{
/* Some debugging code */
dbg
(
"uhci_result_control() failed with status %x"
,
status
);
dev_dbg
(
uhci_dev
(
uhci
),
"%s: failed with status %x
\n
"
,
__FUNCTION__
,
status
);
if
(
errbuf
)
{
/* Print the chain for debugging purposes */
...
...
@@ -1238,7 +1233,8 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb)
#if 0
if ((debug == 1 && ret != -EPIPE) || debug > 1) {
/* Some debugging code */
dbg("uhci_result_common() failed with status %x", status);
dev_dbg(uhci_dev(uhci), "%s: failed with status %x\n",
__FUNCTION__, status);
if (errbuf) {
/* Print the chain for debugging purposes */
...
...
@@ -1255,7 +1251,7 @@ static inline int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb, struc
{
int
ret
;
/* Can't have low
speed bulk transfers */
/* Can't have low
-
speed bulk transfers */
if
(
urb
->
dev
->
speed
==
USB_SPEED_LOW
)
return
-
EINVAL
;
...
...
@@ -1462,11 +1458,14 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, int mem_flags)
spin_lock_irqsave
(
&
uhci
->
urb_list_lock
,
flags
);
if
(
urb
->
status
!=
-
EINPROGRESS
)
/* URB already unlinked! */
goto
out
;
eurb
=
uhci_find_urb_ep
(
uhci
,
urb
);
if
(
!
uhci_alloc_urb_priv
(
uhci
,
urb
))
{
spin_unlock_irqrestore
(
&
uhci
->
urb_list_lock
,
flags
)
;
return
-
ENOMEM
;
ret
=
-
ENOMEM
;
goto
out
;
}
switch
(
usb_pipetype
(
urb
->
pipe
))
{
...
...
@@ -1514,10 +1513,11 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, int mem_flags)
return
ret
;
}
ret
=
0
;
out:
spin_unlock_irqrestore
(
&
uhci
->
urb_list_lock
,
flags
);
return
0
;
return
ret
;
}
/*
...
...
@@ -1527,18 +1527,15 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, int mem_flags)
*/
static
void
uhci_transfer_result
(
struct
uhci_hcd
*
uhci
,
struct
urb
*
urb
)
{
int
ret
=
-
EINVAL
;
unsigned
long
flags
;
int
ret
=
-
EINPROGRESS
;
struct
urb_priv
*
urbp
;
spin_lock
_irqsave
(
&
urb
->
lock
,
flags
);
spin_lock
(
&
urb
->
lock
);
urbp
=
(
struct
urb_priv
*
)
urb
->
hcpriv
;
if
(
urb
->
status
!=
-
EINPROGRESS
)
{
info
(
"uhci_transfer_result: called for URB %p not in flight?"
,
urb
);
if
(
urb
->
status
!=
-
EINPROGRESS
)
/* URB already dequeued */
goto
out
;
}
switch
(
usb_pipetype
(
urb
->
pipe
))
{
case
PIPE_CONTROL
:
...
...
@@ -1555,10 +1552,9 @@ static void uhci_transfer_result(struct uhci_hcd *uhci, struct urb *urb)
break
;
}
urbp
->
status
=
ret
;
if
(
ret
==
-
EINPROGRESS
)
goto
out
;
urb
->
status
=
ret
;
switch
(
usb_pipetype
(
urb
->
pipe
))
{
case
PIPE_CONTROL
:
...
...
@@ -1585,17 +1581,16 @@ static void uhci_transfer_result(struct uhci_hcd *uhci, struct urb *urb)
uhci_unlink_generic
(
uhci
,
urb
);
break
;
default:
info
(
"uhci_transfer_result: unknown pipe type %d for urb %p
\n
"
,
usb_pipetype
(
urb
->
pipe
),
urb
);
dev_info
(
uhci_dev
(
uhci
),
"%s: unknown pipe type %d "
"for urb %p
\n
"
,
__FUNCTION__
,
usb_pipetype
(
urb
->
pipe
),
urb
);
}
/* Remove it from uhci->urb_list */
list_del_init
(
&
urbp
->
urb_list
);
uhci_add_complete
(
uhci
,
urb
);
/* Move it from uhci->urb_list to uhci->complete_list */
uhci_moveto_complete
(
uhci
,
urbp
);
out:
spin_unlock
_irqrestore
(
&
urb
->
lock
,
flags
);
spin_unlock
(
&
urb
->
lock
);
}
/*
...
...
@@ -1607,10 +1602,6 @@ static void uhci_unlink_generic(struct uhci_hcd *uhci, struct urb *urb)
struct
urb_priv
*
urbp
=
(
struct
urb_priv
*
)
urb
->
hcpriv
;
int
prevactive
=
1
;
/* We can get called when urbp allocation fails, so check */
if
(
!
urbp
)
return
;
uhci_dec_fsbr
(
uhci
,
urb
);
/* Safe since it checks */
/*
...
...
@@ -1660,13 +1651,6 @@ static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
unsigned
long
flags
;
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
);
list_del_init
(
&
urbp
->
urb_list
);
...
...
@@ -1678,7 +1662,7 @@ static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
/* If we're the first, set the next interrupt bit */
if
(
list_empty
(
&
uhci
->
urb_remove_list
))
uhci_set_next_interrupt
(
uhci
);
list_add
(
&
urbp
->
urb_list
,
&
uhci
->
urb_remove_list
);
list_add
_tail
(
&
urbp
->
urb_list
,
&
uhci
->
urb_remove_list
);
spin_unlock
(
&
uhci
->
urb_remove_list_lock
);
spin_unlock_irqrestore
(
&
uhci
->
urb_list_lock
,
flags
);
...
...
@@ -1805,9 +1789,8 @@ static int init_stall_timer(struct usb_hcd *hcd)
static
void
uhci_free_pending_qhs
(
struct
uhci_hcd
*
uhci
)
{
struct
list_head
*
tmp
,
*
head
;
unsigned
long
flags
;
spin_lock
_irqsave
(
&
uhci
->
qh_remove_list_lock
,
flags
);
spin_lock
(
&
uhci
->
qh_remove_list_lock
);
head
=
&
uhci
->
qh_remove_list
;
tmp
=
head
->
next
;
while
(
tmp
!=
head
)
{
...
...
@@ -1819,15 +1802,14 @@ static void uhci_free_pending_qhs(struct uhci_hcd *uhci)
uhci_free_qh
(
uhci
,
qh
);
}
spin_unlock
_irqrestore
(
&
uhci
->
qh_remove_list_lock
,
flags
);
spin_unlock
(
&
uhci
->
qh_remove_list_lock
);
}
static
void
uhci_free_pending_tds
(
struct
uhci_hcd
*
uhci
)
{
struct
list_head
*
tmp
,
*
head
;
unsigned
long
flags
;
spin_lock
_irqsave
(
&
uhci
->
td_remove_list_lock
,
flags
);
spin_lock
(
&
uhci
->
td_remove_list_lock
);
head
=
&
uhci
->
td_remove_list
;
tmp
=
head
->
next
;
while
(
tmp
!=
head
)
{
...
...
@@ -1839,23 +1821,16 @@ static void uhci_free_pending_tds(struct uhci_hcd *uhci)
uhci_free_td
(
uhci
,
td
);
}
spin_unlock
_irqrestore
(
&
uhci
->
td_remove_list_lock
,
flags
);
spin_unlock
(
&
uhci
->
td_remove_list_lock
);
}
static
void
uhci_finish_urb
(
struct
usb_hcd
*
hcd
,
struct
urb
*
urb
,
struct
pt_regs
*
regs
)
{
struct
urb_priv
*
urbp
=
(
struct
urb_priv
*
)
urb
->
hcpriv
;
struct
uhci_hcd
*
uhci
=
hcd_to_uhci
(
hcd
);
int
status
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
urb
->
lock
,
flags
);
status
=
urbp
->
status
;
spin_lock
(
&
urb
->
lock
);
uhci_destroy_urb_priv
(
uhci
,
urb
);
if
(
urb
->
status
!=
-
ENOENT
&&
urb
->
status
!=
-
ECONNRESET
)
urb
->
status
=
status
;
spin_unlock_irqrestore
(
&
urb
->
lock
,
flags
);
spin_unlock
(
&
urb
->
lock
);
usb_hcd_giveback_urb
(
hcd
,
urb
,
regs
);
}
...
...
@@ -1864,48 +1839,40 @@ static void uhci_finish_completion(struct usb_hcd *hcd, struct pt_regs *regs)
{
struct
uhci_hcd
*
uhci
=
hcd_to_uhci
(
hcd
);
struct
list_head
*
tmp
,
*
head
;
unsigned
long
flags
;
spin_lock
_irqsave
(
&
uhci
->
complete_list_lock
,
flags
);
spin_lock
(
&
uhci
->
complete_list_lock
);
head
=
&
uhci
->
complete_list
;
tmp
=
head
->
next
;
while
(
tmp
!=
head
)
{
struct
urb_priv
*
urbp
=
list_entry
(
tmp
,
struct
urb_priv
,
complete
_list
);
struct
urb_priv
*
urbp
=
list_entry
(
tmp
,
struct
urb_priv
,
urb
_list
);
struct
urb
*
urb
=
urbp
->
urb
;
list_del_init
(
&
urbp
->
complete
_list
);
spin_unlock
_irqrestore
(
&
uhci
->
complete_list_lock
,
flags
);
list_del_init
(
&
urbp
->
urb
_list
);
spin_unlock
(
&
uhci
->
complete_list_lock
);
uhci_finish_urb
(
hcd
,
urb
,
regs
);
spin_lock
_irqsave
(
&
uhci
->
complete_list_lock
,
flags
);
spin_lock
(
&
uhci
->
complete_list_lock
);
head
=
&
uhci
->
complete_list
;
tmp
=
head
->
next
;
}
spin_unlock
_irqrestore
(
&
uhci
->
complete_list_lock
,
flags
);
spin_unlock
(
&
uhci
->
complete_list_lock
);
}
static
void
uhci_remove_pending_
qh
s
(
struct
uhci_hcd
*
uhci
)
static
void
uhci_remove_pending_
urbp
s
(
struct
uhci_hcd
*
uhci
)
{
struct
list_head
*
tmp
,
*
head
;
unsigned
long
flags
;
spin_lock
_irqsave
(
&
uhci
->
urb_remove_list_lock
,
flags
);
spin_lock
(
&
uhci
->
urb_remove_list_lock
);
head
=
&
uhci
->
urb_remove_list
;
tmp
=
head
->
next
;
while
(
tmp
!=
head
)
{
struct
urb_priv
*
urbp
=
list_entry
(
tmp
,
struct
urb_priv
,
urb_list
);
struct
urb
*
urb
=
urbp
->
urb
;
tmp
=
tmp
->
next
;
list_del_init
(
&
urbp
->
urb_list
);
urbp
->
status
=
urb
->
status
=
-
ECONNRESET
;
uhci_add_complete
(
uhci
,
urb
);
uhci_moveto_complete
(
uhci
,
urbp
);
}
spin_unlock
_irqrestore
(
&
uhci
->
urb_remove_list_lock
,
flags
);
spin_unlock
(
&
uhci
->
urb_remove_list_lock
);
}
static
irqreturn_t
uhci_irq
(
struct
usb_hcd
*
hcd
,
struct
pt_regs
*
regs
)
...
...
@@ -1917,20 +1884,24 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
/*
* Read the interrupt status, and write it back to clear the
* interrupt cause
* interrupt cause. Contrary to the UHCI specification, the
* "HC Halted" status bit is persistent: it is RO, not R/WC.
*/
status
=
inw
(
io_addr
+
USBSTS
);
if
(
!
status
)
/* shared interrupt, not mine */
if
(
!
(
status
&
~
USBSTS_HCH
)
)
/* shared interrupt, not mine */
return
IRQ_NONE
;
outw
(
status
,
io_addr
+
USBSTS
);
/* Clear it */
if
(
status
&
~
(
USBSTS_USBINT
|
USBSTS_ERROR
|
USBSTS_RD
))
{
if
(
status
&
USBSTS_HSE
)
err
(
"%x: host system error, PCI problems?"
,
io_addr
);
dev_err
(
uhci_dev
(
uhci
),
"host system error, "
"PCI problems?
\n
"
);
if
(
status
&
USBSTS_HCPE
)
err
(
"%x: host controller process error. something bad happened"
,
io_addr
);
dev_err
(
uhci_dev
(
uhci
),
"host controller process "
"error, something bad happened!
\n
"
);
if
((
status
&
USBSTS_HCH
)
&&
uhci
->
state
>
0
)
{
err
(
"%x: host controller halted. very bad"
,
io_addr
);
dev_err
(
uhci_dev
(
uhci
),
"host controller halted, "
"very bad!
\n
"
);
/* FIXME: Reset the controller, fix the offending TD */
}
}
...
...
@@ -1942,7 +1913,7 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
uhci_free_pending_tds
(
uhci
);
uhci_remove_pending_
qh
s
(
uhci
);
uhci_remove_pending_
urbp
s
(
uhci
);
uhci_clear_next_interrupt
(
uhci
);
...
...
@@ -1986,7 +1957,7 @@ static void suspend_hc(struct uhci_hcd *uhci)
{
unsigned
int
io_addr
=
uhci
->
io_addr
;
d
bg
(
"%x: suspend_hc"
,
io_addr
);
d
ev_dbg
(
uhci_dev
(
uhci
),
"%s
\n
"
,
__FUNCTION__
);
uhci
->
state
=
UHCI_SUSPENDED
;
uhci
->
resume_detect
=
0
;
outw
(
USBCMD_EGSM
,
io_addr
+
USBCMD
);
...
...
@@ -1998,7 +1969,7 @@ static void wakeup_hc(struct uhci_hcd *uhci)
switch
(
uhci
->
state
)
{
case
UHCI_SUSPENDED
:
/* Start the resume */
d
bg
(
"%x: wakeup_hc"
,
io_addr
);
d
ev_dbg
(
uhci_dev
(
uhci
),
"%s
\n
"
,
__FUNCTION__
);
/* Global resume for >= 20ms */
outw
(
USBCMD_FGR
|
USBCMD_EGSM
,
io_addr
+
USBCMD
);
...
...
@@ -2049,7 +2020,7 @@ static int suspend_allowed(struct uhci_hcd *uhci)
unsigned
int
io_addr
=
uhci
->
io_addr
;
int
i
;
if
(
!
uhci
->
hcd
.
pdev
||
uhci
->
hcd
.
pdev
->
vendor
!=
PCI_VENDOR_ID_INTEL
)
if
(
to_pci_dev
(
uhci_dev
(
uhci
))
->
vendor
!=
PCI_VENDOR_ID_INTEL
)
return
1
;
/* Some of Intel's USB controllers have a bug that causes false
...
...
@@ -2123,7 +2094,7 @@ static void start_hc(struct uhci_hcd *uhci)
outw
(
USBCMD_HCRESET
,
io_addr
+
USBCMD
);
while
(
inw
(
io_addr
+
USBCMD
)
&
USBCMD_HCRESET
)
{
if
(
!--
timeout
)
{
printk
(
KERN_ERR
"uhci:
USBCMD_HCRESET timed out!
\n
"
);
dev_err
(
uhci_dev
(
uhci
),
"
USBCMD_HCRESET timed out!
\n
"
);
break
;
}
}
...
...
@@ -2163,17 +2134,18 @@ static void release_uhci(struct uhci_hcd *uhci)
}
if
(
uhci
->
qh_pool
)
{
pci
_pool_destroy
(
uhci
->
qh_pool
);
dma
_pool_destroy
(
uhci
->
qh_pool
);
uhci
->
qh_pool
=
NULL
;
}
if
(
uhci
->
td_pool
)
{
pci
_pool_destroy
(
uhci
->
td_pool
);
dma
_pool_destroy
(
uhci
->
td_pool
);
uhci
->
td_pool
=
NULL
;
}
if
(
uhci
->
fl
)
{
pci_free_consistent
(
uhci
->
hcd
.
pdev
,
sizeof
(
*
uhci
->
fl
),
uhci
->
fl
,
uhci
->
fl
->
dma_handle
);
dma_free_coherent
(
uhci_dev
(
uhci
),
sizeof
(
*
uhci
->
fl
),
uhci
->
fl
,
uhci
->
fl
->
dma_handle
);
uhci
->
fl
=
NULL
;
}
...
...
@@ -2198,7 +2170,8 @@ static int uhci_reset(struct usb_hcd *hcd)
* interrupts from any previous setup.
*/
reset_hc
(
uhci
);
pci_write_config_word
(
hcd
->
pdev
,
USBLEGSUP
,
USBLEGSUP_DEFAULT
);
pci_write_config_word
(
to_pci_dev
(
uhci_dev
(
uhci
)),
USBLEGSUP
,
USBLEGSUP_DEFAULT
);
return
0
;
}
...
...
@@ -2213,10 +2186,10 @@ static int uhci_reset(struct usb_hcd *hcd)
* of the queues. We don't do that here, because
* we'll create the actual TD entries on demand.
* - The first queue is the interrupt queue.
* - The second queue is the control queue, split into low
and high
speed
* - The second queue is the control queue, split into low
- and full-
speed
* - The third queue is bulk queue.
* - The fourth queue is the bandwidth reclamation queue, which loops back
* to the
high
speed control queue.
* to the
full-
speed control queue.
*/
static
int
uhci_start
(
struct
usb_hcd
*
hcd
)
{
...
...
@@ -2230,12 +2203,12 @@ static int uhci_start(struct usb_hcd *hcd)
struct
proc_dir_entry
*
ent
;
#endif
io_size
=
pci_resource_len
(
hcd
->
pdev
,
hcd
->
region
);
io_size
=
pci_resource_len
(
to_pci_dev
(
uhci_dev
(
uhci
))
,
hcd
->
region
);
#ifdef CONFIG_PROC_FS
ent
=
create_proc_entry
(
hcd
->
self
.
bus_name
,
S_IFREG
|
S_IRUGO
|
S_IWUSR
,
uhci_proc_root
);
if
(
!
ent
)
{
err
(
"couldn't create uhci proc entry
"
);
dev_err
(
uhci_dev
(
uhci
),
"couldn't create uhci proc entry
\n
"
);
retval
=
-
ENOMEM
;
goto
err_create_proc_entry
;
}
...
...
@@ -2266,9 +2239,11 @@ static int uhci_start(struct usb_hcd *hcd)
spin_lock_init
(
&
uhci
->
frame_list_lock
);
uhci
->
fl
=
pci_alloc_consistent
(
hcd
->
pdev
,
sizeof
(
*
uhci
->
fl
),
&
dma_handle
);
uhci
->
fl
=
dma_alloc_coherent
(
uhci_dev
(
uhci
),
sizeof
(
*
uhci
->
fl
),
&
dma_handle
,
0
);
if
(
!
uhci
->
fl
)
{
err
(
"unable to allocate consistent memory for frame list"
);
dev_err
(
uhci_dev
(
uhci
),
"unable to allocate "
"consistent memory for frame list
\n
"
);
goto
err_alloc_fl
;
}
...
...
@@ -2276,17 +2251,17 @@ static int uhci_start(struct usb_hcd *hcd)
uhci
->
fl
->
dma_handle
=
dma_handle
;
uhci
->
td_pool
=
pci_pool_create
(
"uhci_td"
,
hcd
->
pdev
,
uhci
->
td_pool
=
dma_pool_create
(
"uhci_td"
,
uhci_dev
(
uhci
)
,
sizeof
(
struct
uhci_td
),
16
,
0
);
if
(
!
uhci
->
td_pool
)
{
err
(
"unable to create td pci_pool
"
);
dev_err
(
uhci_dev
(
uhci
),
"unable to create td dma_pool
\n
"
);
goto
err_create_td_pool
;
}
uhci
->
qh_pool
=
pci_pool_create
(
"uhci_qh"
,
hcd
->
pdev
,
uhci
->
qh_pool
=
dma_pool_create
(
"uhci_qh"
,
uhci_dev
(
uhci
)
,
sizeof
(
struct
uhci_qh
),
16
,
0
);
if
(
!
uhci
->
qh_pool
)
{
err
(
"unable to create qh pci_pool
"
);
dev_err
(
uhci_dev
(
uhci
),
"unable to create qh dma_pool
\n
"
);
goto
err_create_qh_pool
;
}
...
...
@@ -2304,12 +2279,13 @@ static int uhci_start(struct usb_hcd *hcd)
break
;
}
if
(
debug
)
info
(
"detected %d ports
"
,
port
);
dev_info
(
uhci_dev
(
uhci
),
"detected %d ports
\n
"
,
port
);
/* This is experimental so anything less than 2 or greater than 8 is */
/* something weird and we'll ignore it */
if
(
port
<
2
||
port
>
8
)
{
info
(
"port count misdetected? forcing to 2 ports"
);
if
(
port
<
2
||
port
>
UHCI_RH_MAXCHILD
)
{
dev_info
(
uhci_dev
(
uhci
),
"port count misdetected? "
"forcing to 2 ports
\n
"
);
port
=
2
;
}
...
...
@@ -2317,35 +2293,36 @@ static int uhci_start(struct usb_hcd *hcd)
hcd
->
self
.
root_hub
=
udev
=
usb_alloc_dev
(
NULL
,
&
hcd
->
self
,
0
);
if
(
!
udev
)
{
err
(
"unable to allocate root hub
"
);
dev_err
(
uhci_dev
(
uhci
),
"unable to allocate root hub
\n
"
);
goto
err_alloc_root_hub
;
}
uhci
->
term_td
=
uhci_alloc_td
(
uhci
,
udev
);
if
(
!
uhci
->
term_td
)
{
err
(
"unable to allocate terminating TD
"
);
dev_err
(
uhci_dev
(
uhci
),
"unable to allocate terminating TD
\n
"
);
goto
err_alloc_term_td
;
}
for
(
i
=
0
;
i
<
UHCI_NUM_SKELQH
;
i
++
)
{
uhci
->
skelqh
[
i
]
=
uhci_alloc_qh
(
uhci
,
udev
);
if
(
!
uhci
->
skelqh
[
i
])
{
err
(
"unable to allocate QH %d"
,
i
);
dev_err
(
uhci_dev
(
uhci
),
"unable to allocate QH
\n
"
);
goto
err_alloc_skelqh
;
}
}
/*
* 8 Interrupt queues; link
int2 to int1, int4 to int2, etc
* 8 Interrupt queues; link
all higher int queues to int1,
* 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_int128_qh
->
link
=
uhci
->
skel_int64_qh
->
link
=
uhci
->
skel_int32_qh
->
link
=
uhci
->
skel_int16_qh
->
link
=
uhci
->
skel_int8_qh
->
link
=
uhci
->
skel_int4_qh
->
link
=
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
;
...
...
@@ -2361,39 +2338,33 @@ static int uhci_start(struct usb_hcd *hcd)
uhci
->
skel_term_qh
->
element
=
cpu_to_le32
(
uhci
->
term_td
->
dma_handle
);
/*
* Fill the frame list: make all entries point to
*
the proper
interrupt queue.
* Fill the frame list: make all entries point to
the proper
* interrupt queue.
*
* This is probably silly, but it's a simple way to
* scatter the interrupt queues in a way that gives
* us a reasonable dynamic range for irq latencies.
* The interrupt queues will be interleaved as evenly as possible.
* There's not much to be done about period-1 interrupts; they have
* to occur in every frame. But we can schedule period-2 interrupts
* in odd-numbered frames, period-4 interrupts in frames congruent
* to 2 (mod 4), and so on. This way each frame only has two
* interrupt QHs, which will help spread out bandwidth utilization.
*/
for
(
i
=
0
;
i
<
UHCI_NUMFRAMES
;
i
++
)
{
int
irq
=
0
;
int
irq
;
if
(
i
&
1
)
{
irq
++
;
if
(
i
&
2
)
{
irq
++
;
if
(
i
&
4
)
{
irq
++
;
if
(
i
&
8
)
{
irq
++
;
if
(
i
&
16
)
{
irq
++
;
if
(
i
&
32
)
{
irq
++
;
if
(
i
&
64
)
irq
++
;
}
}
}
}
}
}
/*
* ffs (Find First bit Set) does exactly what we need:
* 1,3,5,... => ffs = 0 => use skel_int2_qh = skelqh[6],
* 2,6,10,... => ffs = 1 => use skel_int4_qh = skelqh[5], etc.
* ffs > 6 => not on any high-period queue, so use
* skel_int1_qh = skelqh[7].
* Add UHCI_NUMFRAMES to insure at least one bit is set.
*/
irq
=
6
-
(
int
)
__ffs
(
i
+
UHCI_NUMFRAMES
);
if
(
irq
<
0
)
irq
=
7
;
/* Only place we don't use the frame list routines */
uhci
->
fl
->
frame
[
i
]
=
cpu_to_le32
(
uhci
->
skelqh
[
7
-
irq
]
->
dma_handle
);
uhci
->
fl
->
frame
[
i
]
=
cpu_to_le32
(
uhci
->
skelqh
[
irq
]
->
dma_handle
);
}
start_hc
(
uhci
);
...
...
@@ -2402,8 +2373,8 @@ static int uhci_start(struct usb_hcd *hcd)
udev
->
speed
=
USB_SPEED_FULL
;
if
(
usb_register_root_hub
(
udev
,
&
hcd
->
pdev
->
dev
)
!=
0
)
{
err
(
"unable to start root hub
"
);
if
(
usb_register_root_hub
(
udev
,
uhci_dev
(
uhci
)
)
!=
0
)
{
dev_err
(
uhci_dev
(
uhci
),
"unable to start root hub
\n
"
);
retval
=
-
ENOMEM
;
goto
err_start_root_hub
;
}
...
...
@@ -2433,15 +2404,16 @@ static int uhci_start(struct usb_hcd *hcd)
hcd
->
self
.
root_hub
=
NULL
;
err_alloc_root_hub:
pci
_pool_destroy
(
uhci
->
qh_pool
);
dma
_pool_destroy
(
uhci
->
qh_pool
);
uhci
->
qh_pool
=
NULL
;
err_create_qh_pool:
pci
_pool_destroy
(
uhci
->
td_pool
);
dma
_pool_destroy
(
uhci
->
td_pool
);
uhci
->
td_pool
=
NULL
;
err_create_td_pool:
pci_free_consistent
(
hcd
->
pdev
,
sizeof
(
*
uhci
->
fl
),
uhci
->
fl
,
uhci
->
fl
->
dma_handle
);
dma_free_coherent
(
uhci_dev
(
uhci
),
sizeof
(
*
uhci
->
fl
),
uhci
->
fl
,
uhci
->
fl
->
dma_handle
);
uhci
->
fl
=
NULL
;
err_alloc_fl:
...
...
@@ -2458,6 +2430,7 @@ static int uhci_start(struct usb_hcd *hcd)
static
void
uhci_stop
(
struct
usb_hcd
*
hcd
)
{
struct
uhci_hcd
*
uhci
=
hcd_to_uhci
(
hcd
);
unsigned
long
flags
;
del_timer_sync
(
&
uhci
->
stall_timer
);
...
...
@@ -2465,14 +2438,16 @@ static void uhci_stop(struct usb_hcd *hcd)
* At this point, we're guaranteed that no new connects can be made
* to this bus since there are no more parents
*/
local_irq_save
(
flags
);
uhci_free_pending_qhs
(
uhci
);
uhci_free_pending_tds
(
uhci
);
uhci_remove_pending_
qh
s
(
uhci
);
uhci_remove_pending_
urbp
s
(
uhci
);
reset_hc
(
uhci
);
uhci_free_pending_qhs
(
uhci
);
uhci_free_pending_tds
(
uhci
);
local_irq_restore
(
flags
);
release_uhci
(
uhci
);
}
...
...
@@ -2494,7 +2469,7 @@ static int uhci_resume(struct usb_hcd *hcd)
{
struct
uhci_hcd
*
uhci
=
hcd_to_uhci
(
hcd
);
pci_set_master
(
uhci
->
hcd
.
pdev
);
pci_set_master
(
to_pci_dev
(
uhci_dev
(
uhci
))
);
if
(
uhci
->
state
==
UHCI_SUSPENDED
)
uhci
->
resume_detect
=
1
;
...
...
@@ -2586,7 +2561,7 @@ static int __init uhci_hcd_init(void)
{
int
retval
=
-
ENOMEM
;
info
(
DRIVER_DESC
" "
DRIVER_VERSION
);
printk
(
KERN_INFO
DRIVER_DESC
" "
DRIVER_VERSION
"
\n
"
);
if
(
usb_disabled
())
return
-
ENODEV
;
...
...
@@ -2616,7 +2591,7 @@ static int __init uhci_hcd_init(void)
init_failed:
if
(
kmem_cache_destroy
(
uhci_up_cachep
))
printk
(
KERN_INFO
"uhci: not all urb_priv's were freed
\n
"
);
warn
(
"not all urb_priv's were freed!
"
);
up_failed:
...
...
@@ -2638,7 +2613,7 @@ static void __exit uhci_hcd_cleanup(void)
pci_unregister_driver
(
&
uhci_pci_driver
);
if
(
kmem_cache_destroy
(
uhci_up_cachep
))
printk
(
KERN_INFO
"uhci: not all urb_priv's were freed
\n
"
);
warn
(
"not all urb_priv's were freed!
"
);
#ifdef CONFIG_PROC_FS
remove_proc_entry
(
"driver/uhci"
,
0
);
...
...
@@ -2654,4 +2629,3 @@ module_exit(uhci_hcd_cleanup);
MODULE_AUTHOR
(
DRIVER_AUTHOR
);
MODULE_DESCRIPTION
(
DRIVER_DESC
);
MODULE_LICENSE
(
"GPL"
);
drivers/usb/host/uhci-hcd.h
View file @
cdb7bc8f
...
...
@@ -49,12 +49,19 @@
#define USBPORTSC_CSC 0x0002
/* Connect Status Change */
#define USBPORTSC_PE 0x0004
/* Port Enable */
#define USBPORTSC_PEC 0x0008
/* Port Enable Change */
#define USBPORTSC_LS 0x0030
/* Line Status */
#define USBPORTSC_DPLUS 0x0010
/* D+ high (line status) */
#define USBPORTSC_DMINUS 0x0020
/* D- high (line status) */
#define USBPORTSC_RD 0x0040
/* Resume Detect */
#define USBPORTSC_RES1 0x0080
/* reserved, always 1 */
#define USBPORTSC_LSDA 0x0100
/* Low Speed Device Attached */
#define USBPORTSC_PR 0x0200
/* Port Reset */
/* OC and OCC from Intel 430TX and later (not UHCI 1.1d spec) */
#define USBPORTSC_OC 0x0400
/* Over Current condition */
#define USBPORTSC_OCC 0x0800
/* Over Current Change R/WC */
#define USBPORTSC_SUSP 0x1000
/* Suspend */
#define USBPORTSC_RES2 0x2000
/* reserved, write zeroes */
#define USBPORTSC_RES3 0x4000
/* reserved, write zeroes */
#define USBPORTSC_RES4 0x8000
/* reserved, write zeroes */
/* Legacy support register */
#define USBLEGSUP 0xc0
...
...
@@ -200,8 +207,8 @@ struct uhci_td {
* The UHCI driver places Interrupt, Control and Bulk into QH's both
* to group together TD's for one transfer, and also to faciliate queuing
* 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
* control,
high
speed control and terminating QH (see explanation for
* a skeleton of QH's for each predefined Interrupt latency, low
-
speed
* control,
full-
speed control and terminating QH (see explanation for
* the terminating QH below).
*
* When we want to add a new QH, we add it to the end of the list for the
...
...
@@ -216,9 +223,9 @@ struct uhci_td {
* skel int32 QH
* ...
* skel int1 QH
* skel low
speed control QH
* skel low
-
speed control QH
* dev 5 control QH
* skel
high
speed control QH
* skel
full-
speed control QH
* skel bulk QH
* dev 1 bulk QH
* dev 2 bulk QH
...
...
@@ -227,7 +234,7 @@ struct uhci_td {
* The terminating QH is used for 2 reasons:
* - 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
* - To loop back to the
full-speed control queue for full-
speed bandwidth
* reclamation
*
* Isochronous transfers are stored before the start of the skeleton
...
...
@@ -308,6 +315,7 @@ enum uhci_state {
};
#define hcd_to_uhci(hcd_ptr) container_of(hcd_ptr, struct uhci_hcd, hcd)
#define uhci_dev(u) ((u)->hcd.self.controller)
/*
* This describes the full uhci information.
...
...
@@ -326,8 +334,8 @@ struct uhci_hcd {
/* Grabbed from PCI */
unsigned
long
io_addr
;
struct
pci
_pool
*
qh_pool
;
struct
pci
_pool
*
td_pool
;
struct
dma
_pool
*
qh_pool
;
struct
dma
_pool
*
td_pool
;
struct
usb_bus
*
bus
;
...
...
@@ -336,7 +344,7 @@ struct uhci_hcd {
spinlock_t
frame_list_lock
;
struct
uhci_frame_list
*
fl
;
/* P: uhci->frame_list_lock */
int
fsbr
;
/* Full
speed bandwidth reclamation */
int
fsbr
;
/* Full
-
speed bandwidth reclamation */
unsigned
long
fsbrtimeout
;
/* FSBR delay */
enum
uhci_state
state
;
/* FIXME: needs a spinlock */
...
...
@@ -383,13 +391,10 @@ struct urb_priv {
/* a control transfer, retrigger */
/* the status phase */
int
status
;
/* Final status */
unsigned
long
inserttime
;
/* In jiffies */
unsigned
long
fsbrtime
;
/* In jiffies */
struct
list_head
queue_list
;
/* P: uhci->frame_list_lock */
struct
list_head
complete_list
;
/* P: uhci->complete_list_lock */
};
/*
...
...
@@ -418,4 +423,3 @@ struct urb_priv {
*/
#endif
drivers/usb/host/uhci-hub.c
View file @
cdb7bc8f
/*
* Universal Host Controller Interface driver for USB.
*
* Maintainer:
Johannes Erdfelt <johannes@erdfelt.com
>
* Maintainer:
Alan Stern <stern@rowland.harvard.edu
>
*
* (C) Copyright 1999 Linus Torvalds
* (C) Copyright 1999-2002 Johannes Erdfelt, johannes@erdfelt.com
...
...
@@ -9,6 +9,7 @@
* (C) Copyright 1999 Georg Acher, acher@in.tum.de
* (C) Copyright 1999 Deti Fliegl, deti@fliegl.de
* (C) Copyright 1999 Thomas Sailer, sailer@ife.ee.ethz.ch
* (C) Copyright 2004 Alan Stern, stern@rowland.harvard.edu
*/
static
__u8
root_hub_hub_des
[]
=
...
...
@@ -16,40 +17,50 @@ static __u8 root_hub_hub_des[] =
0x09
,
/* __u8 bLength; */
0x29
,
/* __u8 bDescriptorType; Hub-descriptor */
0x02
,
/* __u8 bNbrPorts; */
0x0
0
,
/* __u16 wHubCharacteristics; */
0x00
,
0x0
a
,
/* __u16 wHubCharacteristics; */
0x00
,
/* (per-port OC, no power switching) */
0x01
,
/* __u8 bPwrOn2pwrGood; 2ms */
0x00
,
/* __u8 bHubContrCurrent; 0 mA */
0x00
,
/* __u8 DeviceRemovable; *** 7 Ports max *** */
0xff
/* __u8 PortPwrCtrlMask; *** 7 ports max *** */
};
#define UHCI_RH_MAXCHILD 7
/* must write as zeroes */
#define WZ_BITS (USBPORTSC_RES2 | USBPORTSC_RES3 | USBPORTSC_RES4)
/* status change bits: nonzero writes will clear */
#define RWC_BITS (USBPORTSC_OCC | USBPORTSC_PEC | USBPORTSC_CSC)
static
int
uhci_hub_status_data
(
struct
usb_hcd
*
hcd
,
char
*
buf
)
{
struct
uhci_hcd
*
uhci
=
hcd_to_uhci
(
hcd
);
unsigned
int
io_addr
=
uhci
->
io_addr
;
int
i
,
len
=
1
;
int
i
;
*
buf
=
0
;
for
(
i
=
0
;
i
<
uhci
->
rh_numports
;
i
++
)
{
*
buf
|=
((
inw
(
io_addr
+
USBPORTSC1
+
i
*
2
)
&
0xa
)
>
0
?
(
1
<<
(
i
+
1
))
:
0
);
len
=
(
i
+
1
)
/
8
+
1
;
if
(
inw
(
io_addr
+
USBPORTSC1
+
i
*
2
)
&
RWC_BITS
)
*
buf
|=
(
1
<<
(
i
+
1
))
;
}
return
!!*
buf
;
}
#define OK(x) len = (x); break
#define CLR_RH_PORTSTAT(x) \
status = inw(io_addr + USBPORTSC1 + 2 * (wIndex-1)); \
status = (status & 0xfff5) & ~(x); \
outw(status, io_addr + USBPORTSC1 + 2 * (wIndex-1))
status = inw(port_addr); \
status &= ~(RWC_BITS|WZ_BITS); \
status &= ~(x); \
status |= RWC_BITS & (x); \
outw(status, port_addr)
#define SET_RH_PORTSTAT(x) \
status = inw(io_addr + USBPORTSC1 + 2 * (wIndex-1)); \
status = (status & 0xfff5) | (x); \
outw(status, io_addr + USBPORTSC1 + 2 * (wIndex-1))
status = inw(port_addr); \
status |= (x); \
status &= ~(RWC_BITS|WZ_BITS); \
outw(status, port_addr)
/* size of returned buffer is part of USB spec */
...
...
@@ -57,13 +68,9 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
u16
wIndex
,
char
*
buf
,
u16
wLength
)
{
struct
uhci_hcd
*
uhci
=
hcd_to_uhci
(
hcd
);
int
i
,
status
,
retval
=
0
,
len
=
0
;
unsigned
int
io_addr
=
uhci
->
io_addr
;
__u16
cstatus
;
char
c_p_r
[
8
];
for
(
i
=
0
;
i
<
8
;
i
++
)
c_p_r
[
i
]
=
0
;
int
status
,
retval
=
0
,
len
=
0
;
unsigned
int
port_addr
=
uhci
->
io_addr
+
USBPORTSC1
+
2
*
(
wIndex
-
1
);
__u16
wPortChange
,
wPortStatus
;
switch
(
typeReq
)
{
/* Request Destination:
...
...
@@ -78,33 +85,56 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
*
(
__u32
*
)
buf
=
cpu_to_le32
(
0
);
OK
(
4
);
/* hub power */
case
GetPortStatus
:
status
=
inw
(
io_addr
+
USBPORTSC1
+
2
*
(
wIndex
-
1
));
cstatus
=
((
status
&
USBPORTSC_CSC
)
>>
(
1
-
0
))
|
((
status
&
USBPORTSC_PEC
)
>>
(
3
-
1
))
|
(
c_p_r
[
wIndex
-
1
]
<<
(
0
+
4
));
status
=
(
status
&
USBPORTSC_CCS
)
|
((
status
&
USBPORTSC_PE
)
>>
(
2
-
1
))
|
((
status
&
USBPORTSC_SUSP
)
>>
(
12
-
2
))
|
((
status
&
USBPORTSC_PR
)
>>
(
9
-
4
))
|
(
1
<<
8
)
|
/* power on */
((
status
&
USBPORTSC_LSDA
)
<<
(
-
8
+
9
));
*
(
__u16
*
)
buf
=
cpu_to_le16
(
status
);
*
(
__u16
*
)(
buf
+
2
)
=
cpu_to_le16
(
cstatus
);
OK
(
4
);
case
SetHubFeature
:
switch
(
wValue
)
{
case
C_HUB_OVER_CURRENT
:
case
C_HUB_LOCAL_POWER
:
break
;
default:
if
(
!
wIndex
||
wIndex
>
uhci
->
rh_numports
)
goto
err
;
status
=
inw
(
port_addr
);
/* Intel controllers report the OverCurrent bit active on.
* VIA controllers report it active off, so we'll adjust the
* bit value. (It's not standardized in the UHCI spec.)
*/
if
(
to_pci_dev
(
hcd
->
self
.
controller
)
->
vendor
==
PCI_VENDOR_ID_VIA
)
status
^=
USBPORTSC_OC
;
/* UHCI doesn't support C_SUSPEND and C_RESET (always false) */
wPortChange
=
0
;
if
(
status
&
USBPORTSC_CSC
)
wPortChange
|=
1
<<
(
USB_PORT_FEAT_C_CONNECTION
-
16
);
if
(
status
&
USBPORTSC_PEC
)
wPortChange
|=
1
<<
(
USB_PORT_FEAT_C_ENABLE
-
16
);
if
(
status
&
USBPORTSC_OCC
)
wPortChange
|=
1
<<
(
USB_PORT_FEAT_C_OVER_CURRENT
-
16
);
/* UHCI has no power switching (always on) */
wPortStatus
=
1
<<
USB_PORT_FEAT_POWER
;
if
(
status
&
USBPORTSC_CCS
)
wPortStatus
|=
1
<<
USB_PORT_FEAT_CONNECTION
;
if
(
status
&
USBPORTSC_PE
)
{
wPortStatus
|=
1
<<
USB_PORT_FEAT_ENABLE
;
if
(
status
&
(
USBPORTSC_SUSP
|
USBPORTSC_RD
))
wPortStatus
|=
1
<<
USB_PORT_FEAT_SUSPEND
;
}
break
;
if
(
status
&
USBPORTSC_OC
)
wPortStatus
|=
1
<<
USB_PORT_FEAT_OVER_CURRENT
;
if
(
status
&
USBPORTSC_PR
)
wPortStatus
|=
1
<<
USB_PORT_FEAT_RESET
;
if
(
status
&
USBPORTSC_LSDA
)
wPortStatus
|=
1
<<
USB_PORT_FEAT_LOWSPEED
;
if
(
wPortChange
)
dev_dbg
(
uhci_dev
(
uhci
),
"port %d portsc %04x
\n
"
,
wIndex
,
status
);
*
(
__u16
*
)
buf
=
cpu_to_le16
(
wPortStatus
);
*
(
__u16
*
)(
buf
+
2
)
=
cpu_to_le16
(
wPortChange
);
OK
(
4
);
case
SetHubFeature
:
/* We don't implement these */
case
ClearHubFeature
:
switch
(
wValue
)
{
case
C_HUB_OVER_CURRENT
:
OK
(
0
);
/* hub power over current */
case
C_HUB_LOCAL_POWER
:
OK
(
0
);
default:
goto
err
;
}
...
...
@@ -120,17 +150,14 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
case
USB_PORT_FEAT_RESET
:
SET_RH_PORTSTAT
(
USBPORTSC_PR
);
mdelay
(
50
);
/* USB v1.1 7.1.7.3 */
c_p_r
[
wIndex
-
1
]
=
1
;
CLR_RH_PORTSTAT
(
USBPORTSC_PR
);
udelay
(
10
);
SET_RH_PORTSTAT
(
USBPORTSC_PE
);
mdelay
(
10
);
SET_RH_PORTSTAT
(
0xa
);
CLR_RH_PORTSTAT
(
USBPORTSC_PEC
|
USBPORTSC_CSC
);
OK
(
0
);
case
USB_PORT_FEAT_POWER
:
OK
(
0
);
/* port power ** */
case
USB_PORT_FEAT_ENABLE
:
SET_RH_PORTSTAT
(
USBPORTSC_PE
);
/* UHCI has no power switching */
OK
(
0
);
default:
goto
err
;
...
...
@@ -145,31 +172,32 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
CLR_RH_PORTSTAT
(
USBPORTSC_PE
);
OK
(
0
);
case
USB_PORT_FEAT_C_ENABLE
:
SET
_RH_PORTSTAT
(
USBPORTSC_PEC
);
CLR
_RH_PORTSTAT
(
USBPORTSC_PEC
);
OK
(
0
);
case
USB_PORT_FEAT_SUSPEND
:
CLR_RH_PORTSTAT
(
USBPORTSC_SUSP
);
OK
(
0
);
case
USB_PORT_FEAT_C_SUSPEND
:
/*
** WR_RH_PORTSTAT(RH_PS_PSSC);
*/
/*
this driver won't report these
*/
OK
(
0
);
case
USB_PORT_FEAT_POWER
:
OK
(
0
);
/* port power */
/* UHCI has no power switching */
goto
err
;
case
USB_PORT_FEAT_C_CONNECTION
:
SET
_RH_PORTSTAT
(
USBPORTSC_CSC
);
CLR
_RH_PORTSTAT
(
USBPORTSC_CSC
);
OK
(
0
);
case
USB_PORT_FEAT_C_OVER_CURRENT
:
OK
(
0
);
/* port power over current */
CLR_RH_PORTSTAT
(
USBPORTSC_OCC
);
OK
(
0
);
case
USB_PORT_FEAT_C_RESET
:
c_p_r
[
wIndex
-
1
]
=
0
;
/* this driver won't report these */
OK
(
0
);
default:
goto
err
;
}
break
;
case
GetHubDescriptor
:
len
=
min_t
(
unsigned
int
,
wLength
,
min_t
(
unsigned
int
,
sizeof
(
root_hub_hub_des
),
wLength
));
len
=
min_t
(
unsigned
int
,
sizeof
(
root_hub_hub_des
),
wLength
);
memcpy
(
buf
,
root_hub_hub_des
,
len
);
if
(
len
>
2
)
buf
[
2
]
=
uhci
->
rh_numports
;
...
...
@@ -181,4 +209,3 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
return
retval
;
}
drivers/usb/media/stv680.c
View file @
cdb7bc8f
...
...
@@ -490,10 +490,9 @@ static int stv_init (struct usb_stv *stv680)
stv680
->
hue
=
32767
;
stv680
->
palette
=
STV_VIDEO_PALETTE
;
stv680
->
depth
=
24
;
/* rgb24 bits */
swapRGB
=
0
;
if
((
swapRGB_on
==
0
)
&&
(
swapRGB
==
0
))
PDEBUG
(
1
,
"STV(i): swapRGB is (auto) OFF"
);
else
if
((
swapRGB_on
==
1
)
&&
(
swapRGB
==
1
))
else
if
((
swapRGB_on
==
0
)
&&
(
swapRGB
==
1
))
PDEBUG
(
1
,
"STV(i): swapRGB is (auto) ON"
);
else
if
(
swapRGB_on
==
1
)
PDEBUG
(
1
,
"STV(i): swapRGB is (forced) ON"
);
...
...
@@ -657,7 +656,7 @@ static void stv680_video_irq (struct urb *urb, struct pt_regs *regs)
/* Resubmit urb for new data */
urb
->
status
=
0
;
urb
->
dev
=
stv680
->
udev
;
if
(
usb_submit_urb
(
urb
,
GFP_
KERNEL
))
if
(
usb_submit_urb
(
urb
,
GFP_
ATOMIC
))
PDEBUG
(
0
,
"STV(e): urb burned down in video irq"
);
return
;
}
/* _video_irq */
...
...
@@ -1252,13 +1251,10 @@ static int stv680_do_ioctl (struct inode *inode, struct file *file,
return
-
EINVAL
;
}
case
VIDIOCSFBUF
:
return
-
EINVAL
;
case
VIDIOCGTUNER
:
case
VIDIOCSTUNER
:
return
-
EINVAL
;
case
VIDIOCGFREQ
:
case
VIDIOCSFREQ
:
return
-
EINVAL
;
case
VIDIOCGAUDIO
:
case
VIDIOCSAUDIO
:
return
-
EINVAL
;
...
...
@@ -1434,7 +1430,7 @@ static int stv680_probe (struct usb_interface *intf, const struct usb_device_id
if
(
video_register_device
(
stv680
->
vdev
,
VFL_TYPE_GRABBER
,
video_nr
)
==
-
1
)
{
PDEBUG
(
0
,
"STV(e): video_register_device failed"
);
retval
=
-
EIO
;
goto
error
;
goto
error
_vdev
;
}
PDEBUG
(
0
,
"STV(i): registered new video device: video%d"
,
stv680
->
vdev
->
minor
);
...
...
@@ -1442,6 +1438,8 @@ static int stv680_probe (struct usb_interface *intf, const struct usb_device_id
stv680_create_sysfs_files
(
stv680
->
vdev
);
return
0
;
error_vdev:
video_device_release
(
stv680
->
vdev
);
error:
kfree
(
stv680
);
return
retval
;
...
...
@@ -1466,9 +1464,7 @@ static inline void usb_stv680_remove_disconnected (struct usb_stv *stv680)
kfree
(
stv680
->
sbuf
[
i
].
data
);
}
for
(
i
=
0
;
i
<
STV680_NUMSCRATCH
;
i
++
)
if
(
stv680
->
scratch
[
i
].
data
)
{
kfree
(
stv680
->
scratch
[
i
].
data
);
}
PDEBUG
(
0
,
"STV(i): %s disconnected"
,
stv680
->
camera_name
);
/* Free the memory */
...
...
drivers/usb/misc/usbtest.c
View file @
cdb7bc8f
...
...
@@ -724,7 +724,7 @@ struct ctrl_ctx {
int
last
;
};
#define NUM_SUBCASES 1
3
/* how many test subcases here? */
#define NUM_SUBCASES 1
5
/* how many test subcases here? */
struct
subcase
{
struct
usb_ctrlrequest
setup
;
...
...
@@ -952,8 +952,25 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param)
req
.
wValue
=
cpu_to_le16
(
USB_DT_STRING
<<
8
);
// string == 0, for language IDs
len
=
sizeof
(
struct
usb_interface_descriptor
);
// may succeed when > 4 languages
expected
=
EREMOTEIO
;
// or EPIPE, if no strings
break
;
case
13
:
// short read, resembling case 10
req
.
wValue
=
cpu_to_le16
((
USB_DT_CONFIG
<<
8
)
|
0
);
// last data packet "should" be DATA1, not DATA0
len
=
1024
-
udev
->
epmaxpacketin
[
0
];
expected
=
-
EREMOTEIO
;
break
;
case
14
:
// short read; try to fill the last packet
req
.
wValue
=
cpu_to_le16
((
USB_DT_DEVICE
<<
8
)
|
0
);
// device descriptor size == 18 bytes
len
=
udev
->
epmaxpacketin
[
0
];
switch
(
len
)
{
case
8
:
len
=
24
;
break
;
case
16
:
len
=
32
;
break
;
}
expected
=
-
EREMOTEIO
;
break
;
default:
err
(
"bogus number of ctrl queue testcases!"
);
context
.
status
=
-
EINVAL
;
...
...
drivers/usb/serial/ftdi_sio.c
View file @
cdb7bc8f
...
...
@@ -17,6 +17,11 @@
* See http://ftdi-usb-sio.sourceforge.net for upto date testing info
* and extra documentation
*
* (09/Feb/2004) Ian Abbott
* Changed full name of USB-UIRT device to avoid "/" character.
* Added FTDI's alternate PID (0x6006) for FT232/245 devices.
* Added PID for "ELV USB Module UO100" from Stefan Frings.
*
* (21/Oct/2003) Ian Abbott
* Renamed some VID/PID macros for Matrix Orbital and Perle Systems
* devices. Removed Matrix Orbital and Perle Systems devices from the
...
...
@@ -282,6 +287,7 @@ static struct usb_device_id id_table_sio [] = {
static
struct
usb_device_id
id_table_8U232AM
[]
=
{
{
USB_DEVICE_VER
(
FTDI_VID
,
FTDI_8U232AM_PID
,
0
,
0x3ff
)
},
{
USB_DEVICE_VER
(
FTDI_VID
,
FTDI_8U232AM_ALT_PID
,
0
,
0x3ff
)
},
{
USB_DEVICE_VER
(
FTDI_VID
,
FTDI_RELAIS_PID
,
0
,
0x3ff
)
},
{
USB_DEVICE_VER
(
FTDI_NF_RIC_VID
,
FTDI_NF_RIC_PID
,
0
,
0x3ff
)
},
{
USB_DEVICE_VER
(
FTDI_VID
,
FTDI_XF_632_PID
,
0
,
0x3ff
)
},
...
...
@@ -346,12 +352,14 @@ static struct usb_device_id id_table_8U232AM [] = {
{
USB_DEVICE_VER
(
FTDI_VID
,
PROTEGO_R2X0
,
0
,
0x3ff
)
},
{
USB_DEVICE_VER
(
FTDI_VID
,
PROTEGO_SPECIAL_3
,
0
,
0x3ff
)
},
{
USB_DEVICE_VER
(
FTDI_VID
,
PROTEGO_SPECIAL_4
,
0
,
0x3ff
)
},
{
USB_DEVICE_VER
(
FTDI_VID
,
FTDI_ELV_UO100_PID
,
0
,
0x3ff
)
},
{
}
/* Terminating entry */
};
static
struct
usb_device_id
id_table_FT232BM
[]
=
{
{
USB_DEVICE_VER
(
FTDI_VID
,
FTDI_8U232AM_PID
,
0x400
,
0xffff
)
},
{
USB_DEVICE_VER
(
FTDI_VID
,
FTDI_8U232AM_ALT_PID
,
0x400
,
0xffff
)
},
{
USB_DEVICE_VER
(
FTDI_VID
,
FTDI_RELAIS_PID
,
0x400
,
0xffff
)
},
{
USB_DEVICE_VER
(
FTDI_NF_RIC_VID
,
FTDI_NF_RIC_PID
,
0x400
,
0xffff
)
},
{
USB_DEVICE_VER
(
FTDI_VID
,
FTDI_XF_632_PID
,
0x400
,
0xffff
)
},
...
...
@@ -425,6 +433,7 @@ static struct usb_device_id id_table_FT232BM [] = {
{
USB_DEVICE_VER
(
FTDI_VID
,
PROTEGO_R2X0
,
0x400
,
0xffff
)
},
{
USB_DEVICE_VER
(
FTDI_VID
,
PROTEGO_SPECIAL_3
,
0x400
,
0xffff
)
},
{
USB_DEVICE_VER
(
FTDI_VID
,
PROTEGO_SPECIAL_4
,
0x400
,
0xffff
)
},
{
USB_DEVICE_VER
(
FTDI_VID
,
FTDI_ELV_UO100_PID
,
0x400
,
0xffff
)
},
{
}
/* Terminating entry */
};
...
...
@@ -444,6 +453,7 @@ static struct usb_device_id id_table_HE_TIRA1 [] = {
static
struct
usb_device_id
id_table_combined
[]
=
{
{
USB_DEVICE
(
FTDI_VID
,
FTDI_SIO_PID
)
},
{
USB_DEVICE
(
FTDI_VID
,
FTDI_8U232AM_PID
)
},
{
USB_DEVICE
(
FTDI_VID
,
FTDI_8U232AM_ALT_PID
)
},
{
USB_DEVICE
(
FTDI_VID
,
FTDI_RELAIS_PID
)
},
{
USB_DEVICE
(
FTDI_VID
,
FTDI_XF_632_PID
)
},
{
USB_DEVICE
(
FTDI_VID
,
FTDI_XF_634_PID
)
},
...
...
@@ -518,6 +528,7 @@ static struct usb_device_id id_table_combined [] = {
{
USB_DEVICE
(
FTDI_VID
,
PROTEGO_R2X0
)
},
{
USB_DEVICE
(
FTDI_VID
,
PROTEGO_SPECIAL_3
)
},
{
USB_DEVICE
(
FTDI_VID
,
PROTEGO_SPECIAL_4
)
},
{
USB_DEVICE
(
FTDI_VID
,
FTDI_ELV_UO100_PID
)
},
{
}
/* Terminating entry */
};
...
...
@@ -669,7 +680,7 @@ static struct usb_serial_device_type ftdi_FT232BM_device = {
static
struct
usb_serial_device_type
ftdi_USB_UIRT_device
=
{
.
owner
=
THIS_MODULE
,
.
name
=
"USB-UIRT Infrared
Receiver/Transmitt
er"
,
.
name
=
"USB-UIRT Infrared
Tranceiv
er"
,
.
id_table
=
id_table_USB_UIRT
,
.
num_interrupt_in
=
0
,
.
num_bulk_in
=
1
,
...
...
drivers/usb/serial/ftdi_sio.h
View file @
cdb7bc8f
...
...
@@ -25,6 +25,7 @@
#define FTDI_VID 0x0403
/* Vendor Id */
#define FTDI_SIO_PID 0x8372
/* Product Id SIO application of 8U100AX */
#define FTDI_8U232AM_PID 0x6001
/* Similar device to SIO above */
#define FTDI_8U232AM_ALT_PID 0x6006
/* FTDI's alternate PID for above */
#define FTDI_RELAIS_PID 0xFA10
/* Relais device from Rudolf Gugler */
#define FTDI_NF_RIC_VID 0x0DCD
/* Vendor Id */
#define FTDI_NF_RIC_PID 0x0001
/* Product Id */
...
...
@@ -132,6 +133,9 @@
/* http://home.earthlink.net/~jrhees/USBUIRT/index.htm */
#define FTDI_USB_UIRT_PID 0xF850
/* Product Id */
/* ELV USB Module UO100 (PID sent by Stefan Frings) */
#define FTDI_ELV_UO100_PID 0xFB58
/* Product Id */
/*
* Definitions for ID TECH (www.idt-net.com) devices
*/
...
...
drivers/usb/storage/sddr09.c
View file @
cdb7bc8f
...
...
@@ -27,6 +27,20 @@
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* Known vendor commands: 12 bytes, first byte is opcode
*
* E7: read scatter gather
* E8: read
* E9: write
* EA: erase
* EB: reset
* EC: read status
* ED: read ID
* EE: write CIS (?)
* EF: compute checksum (?)
*/
#include "transport.h"
#include "protocol.h"
#include "usb.h"
...
...
@@ -461,6 +475,7 @@ sddr09_read23(struct us_data *us, unsigned long fromaddress,
*
* Always precisely one block is erased; bytes 2-5 and 10-11 are ignored.
* The byte address being erased is 2*Eaddress.
* The CIS cannot be erased.
*/
static
int
sddr09_erase
(
struct
us_data
*
us
,
unsigned
long
Eaddress
)
{
...
...
@@ -486,6 +501,20 @@ sddr09_erase(struct us_data *us, unsigned long Eaddress) {
return
result
;
}
/*
* Write CIS Command: 12 bytes.
* byte 0: opcode: EE
* bytes 2-5: write address in shorts
* bytes 10-11: sector count
*
* This writes at the indicated address. Don't know how it differs
* from E9. Maybe it does not erase? However, it will also write to
* the CIS.
*
* When two such commands on the same page follow each other directly,
* the second one is not done.
*/
/*
* Write Command: 12 bytes.
* byte 0: opcode: E9
...
...
@@ -1478,7 +1507,7 @@ int sddr09_transport(Scsi_Cmnd *srb, struct us_data *us)
"mode page 0x%x
\n
"
,
modepage
);
memcpy
(
ptr
,
mode_page_01
,
sizeof
(
mode_page_01
));
((
u16
*
)
ptr
)[
0
]
=
sizeof
(
mode_page_01
)
-
2
;
((
u16
*
)
ptr
)[
0
]
=
cpu_to_be16
(
sizeof
(
mode_page_01
)
-
2
)
;
ptr
[
3
]
=
(
info
->
flags
&
SDDR09_WP
)
?
0x80
:
0
;
usb_stor_set_xfer_buf
(
ptr
,
sizeof
(
mode_page_01
),
srb
);
return
USB_STOR_TRANSPORT_GOOD
;
...
...
drivers/usb/storage/transport.c
View file @
cdb7bc8f
...
...
@@ -552,6 +552,8 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
return
;
}
srb
->
result
=
SAM_STAT_GOOD
;
/* Determine if we need to auto-sense
*
* I normally don't use a flag like this, but it's almost impossible
...
...
@@ -561,23 +563,14 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
/*
* If we're running the CB transport, which is incapable
* of determining status on it's own, we need to auto-sense almost
* every time.
* of determining status on its own, we need to auto-sense
* unless the operation involved a data-in transfer. Devices
* can signal data-in errors by stalling the bulk-in pipe.
*/
if
(
us
->
protocol
==
US_PR_CB
||
us
->
protocol
==
US_PR_DPCM_USB
)
{
if
((
us
->
protocol
==
US_PR_CB
||
us
->
protocol
==
US_PR_DPCM_USB
)
&&
srb
->
sc_data_direction
!=
SCSI_DATA_READ
)
{
US_DEBUGP
(
"-- CB transport device requiring auto-sense
\n
"
);
need_auto_sense
=
1
;
/* There are some exceptions to this. Notably, if this is
* a UFI device and the command is REQUEST_SENSE or INQUIRY,
* then it is impossible to truly determine status.
*/
if
(
us
->
subclass
==
US_SC_UFI
&&
((
srb
->
cmnd
[
0
]
==
REQUEST_SENSE
)
||
(
srb
->
cmnd
[
0
]
==
INQUIRY
)))
{
US_DEBUGP
(
"** no auto-sense for a special command
\n
"
);
need_auto_sense
=
0
;
}
}
/*
...
...
@@ -591,8 +584,8 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
}
/*
* A
lso, if we have a short transfer on a command that can't have
*
a short transfer, we're going to do this
.
* A
short transfer on a command where we don't expect it
*
is unusual, but it doesn't mean we need to auto-sense
.
*/
if
((
srb
->
resid
>
0
)
&&
!
((
srb
->
cmnd
[
0
]
==
REQUEST_SENSE
)
||
...
...
@@ -601,7 +594,6 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
(
srb
->
cmnd
[
0
]
==
LOG_SENSE
)
||
(
srb
->
cmnd
[
0
]
==
MODE_SENSE_10
)))
{
US_DEBUGP
(
"-- unexpectedly short transfer
\n
"
);
need_auto_sense
=
1
;
}
/* Now, if we need to do the auto-sense, let's do it */
...
...
@@ -614,6 +606,7 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
unsigned
char
old_cmd_len
;
unsigned
char
old_cmnd
[
MAX_COMMAND_SIZE
];
unsigned
long
old_serial_number
;
int
old_resid
;
US_DEBUGP
(
"Issuing auto-REQUEST_SENSE
\n
"
);
...
...
@@ -654,9 +647,12 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
srb
->
serial_number
^=
0x80000000
;
/* issue the auto-sense command */
old_resid
=
srb
->
resid
;
srb
->
resid
=
0
;
temp_result
=
us
->
transport
(
us
->
srb
,
us
);
/* let's clean up right away */
srb
->
resid
=
old_resid
;
srb
->
request_buffer
=
old_request_buffer
;
srb
->
request_bufflen
=
old_request_bufflen
;
srb
->
use_sg
=
old_sg
;
...
...
@@ -698,26 +694,15 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
/* set the result so the higher layers expect this data */
srb
->
result
=
SAM_STAT_CHECK_CONDITION
;
/* If things are really okay, then let's show that */
if
((
srb
->
sense_buffer
[
2
]
&
0xf
)
==
0x0
)
/* If things are really okay, then let's show that. Zero
* out the sense buffer so the higher layers won't realize
* we did an unsolicited auto-sense. */
if
(
result
==
USB_STOR_TRANSPORT_GOOD
&&
(
srb
->
sense_buffer
[
2
]
&
0xf
)
==
0x0
)
{
srb
->
result
=
SAM_STAT_GOOD
;
}
else
/* if (need_auto_sense) */
srb
->
result
=
SAM_STAT_GOOD
;
/* Regardless of auto-sense, if we _know_ we have an error
* condition, show that in the result code
*/
if
(
result
==
USB_STOR_TRANSPORT_FAILED
)
srb
->
result
=
SAM_STAT_CHECK_CONDITION
;
/* If we think we're good, then make sure the sense data shows it.
* This is necessary because the auto-sense for some devices always
* sets byte 0 == 0x70, even if there is no error
*/
if
((
us
->
protocol
==
US_PR_CB
||
us
->
protocol
==
US_PR_DPCM_USB
)
&&
(
result
==
USB_STOR_TRANSPORT_GOOD
)
&&
((
srb
->
sense_buffer
[
2
]
&
0xf
)
==
0x0
))
srb
->
sense_buffer
[
0
]
=
0x0
;
}
}
return
;
/* abort processing: the bulk-only transport requires a reset
...
...
@@ -792,6 +777,10 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
srb
->
request_buffer
,
transfer_length
,
srb
->
use_sg
,
&
srb
->
resid
);
US_DEBUGP
(
"CBI data stage result is 0x%x
\n
"
,
result
);
/* if we stalled the data transfer it means command failed */
if
(
result
==
USB_STOR_XFER_STALLED
)
return
USB_STOR_TRANSPORT_FAILED
;
if
(
result
>
USB_STOR_XFER_STALLED
)
return
USB_STOR_TRANSPORT_ERROR
;
}
...
...
@@ -883,6 +872,10 @@ int usb_stor_CB_transport(Scsi_Cmnd *srb, struct us_data *us)
srb
->
request_buffer
,
transfer_length
,
srb
->
use_sg
,
&
srb
->
resid
);
US_DEBUGP
(
"CB data stage result is 0x%x
\n
"
,
result
);
/* if we stalled the data transfer it means command failed */
if
(
result
==
USB_STOR_XFER_STALLED
)
return
USB_STOR_TRANSPORT_FAILED
;
if
(
result
>
USB_STOR_XFER_STALLED
)
return
USB_STOR_TRANSPORT_ERROR
;
}
...
...
@@ -929,6 +922,7 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
unsigned
int
residue
;
int
result
;
int
fake_sense
=
0
;
unsigned
int
cswlen
;
/* set up the command wrapper */
bcb
->
Signature
=
cpu_to_le32
(
US_BULK_CB_SIGN
);
...
...
@@ -985,7 +979,17 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
/* get CSW for device status */
US_DEBUGP
(
"Attempting to get CSW...
\n
"
);
result
=
usb_stor_bulk_transfer_buf
(
us
,
us
->
recv_bulk_pipe
,
bcs
,
US_BULK_CS_WRAP_LEN
,
NULL
);
bcs
,
US_BULK_CS_WRAP_LEN
,
&
cswlen
);
/* Some broken devices add unnecessary zero-length packets to the
* end of their data transfers. Such packets show up as 0-length
* CSWs. If we encounter such a thing, try to read the CSW again.
*/
if
(
result
==
USB_STOR_XFER_SHORT
&&
cswlen
==
0
)
{
US_DEBUGP
(
"Received 0-length CSW; retrying...
\n
"
);
result
=
usb_stor_bulk_transfer_buf
(
us
,
us
->
recv_bulk_pipe
,
bcs
,
US_BULK_CS_WRAP_LEN
,
&
cswlen
);
}
/* did the attempt to read the CSW fail? */
if
(
result
==
USB_STOR_XFER_STALLED
)
{
...
...
drivers/usb/storage/unusual_devs.h
View file @
cdb7bc8f
...
...
@@ -108,6 +108,15 @@ UNUSUAL_DEV( 0x0482, 0x0103, 0x0100, 0x0100,
"Finecam S5"
,
US_SC_DEVICE
,
US_PR_DEVICE
,
NULL
,
US_FL_FIX_INQUIRY
),
/* Patch for Kyocera Finecam L3
* Submitted by Michael Krauth <michael.krauth@web.de>
*/
UNUSUAL_DEV
(
0x0482
,
0x0105
,
0x0100
,
0x0100
,
"Kyocera"
,
"Finecam L3"
,
US_SC_SCSI
,
US_PR_BULK
,
NULL
,
US_FL_FIX_INQUIRY
),
/* Reported by Paul Stewart <stewart@wetlogic.net>
* This entry is needed because the device reports Sub=ff */
UNUSUAL_DEV
(
0x04a4
,
0x0004
,
0x0001
,
0x0001
,
...
...
@@ -132,7 +141,7 @@ UNUSUAL_DEV( 0x04b8, 0x0602, 0x0110, 0x0110,
UNUSUAL_DEV
(
0x04cb
,
0x0100
,
0x0000
,
0x2210
,
"Fujifilm"
,
"FinePix 1400Zoom"
,
US_SC_
DEVICE
,
US_PR_DEVICE
,
NULL
,
US_FL_FIX_INQUIRY
),
US_SC_
UFI
,
US_PR_DEVICE
,
NULL
,
US_FL_FIX_INQUIRY
),
/* Reported by Peter Wchtler <pwaechtler@loewe-komp.de>
* The device needs the flags only.
...
...
@@ -171,7 +180,7 @@ UNUSUAL_DEV( 0x04e6, 0x0001, 0x0200, 0x0200,
UNUSUAL_DEV
(
0x04e6
,
0x0002
,
0x0100
,
0x0100
,
"Shuttle"
,
"eUSCSI Bridge"
,
US_SC_
SCSI
,
US_PR_BULK
,
usb_stor_euscsi_init
,
US_SC_
DEVICE
,
US_PR_DEVICE
,
usb_stor_euscsi_init
,
US_FL_SCM_MULT_TARG
),
#ifdef CONFIG_USB_STORAGE_SDDR09
...
...
@@ -286,6 +295,13 @@ UNUSUAL_DEV( 0x054c, 0x0032, 0x0000, 0x9999,
US_SC_DEVICE
,
US_PR_DEVICE
,
NULL
,
US_FL_SINGLE_LUN
),
/* Submitted by Michal Mlotek <mlotek@foobar.pl> */
UNUSUAL_DEV
(
0x054c
,
0x0058
,
0x0000
,
0x9999
,
"Sony"
,
"PEG N760c Memorystick"
,
US_SC_DEVICE
,
US_PR_DEVICE
,
NULL
,
US_FL_FIX_INQUIRY
),
UNUSUAL_DEV
(
0x054c
,
0x0069
,
0x0000
,
0x9999
,
"Sony"
,
"Memorystick MSC-U03"
,
...
...
@@ -414,18 +430,6 @@ UNUSUAL_DEV( 0x066b, 0x0105, 0x0100, 0x0100,
US_FL_SINGLE_LUN
),
#endif
/* Submitted by Benny Sjostrand <benny@hostmobility.com> */
UNUSUAL_DEV
(
0x0686
,
0x4011
,
0x0001
,
0x0001
,
"Minolta"
,
"Dimage F300"
,
US_SC_SCSI
,
US_PR_BULK
,
NULL
,
0
),
/* Reported by Miguel A. Fosas <amn3s1a@ono.com> */
UNUSUAL_DEV
(
0x0686
,
0x4017
,
0x0001
,
0x0001
,
"Minolta"
,
"DIMAGE E223"
,
US_SC_SCSI
,
US_PR_DEVICE
,
NULL
,
0
),
/* Following three Minolta cameras reported by Martin Pool
* <mbp@sourcefrog.net>. Originally discovered by Kedar Petankar,
* Matthew Geier, Mikael Lofj"ard, Marcel de Boer.
...
...
@@ -448,6 +452,18 @@ UNUSUAL_DEV( 0x0686, 0x400f, 0x0001, 0x0001,
US_SC_SCSI
,
US_PR_DEVICE
,
NULL
,
0
),
/* Submitted by Benny Sjostrand <benny@hostmobility.com> */
UNUSUAL_DEV
(
0x0686
,
0x4011
,
0x0001
,
0x0001
,
"Minolta"
,
"Dimage F300"
,
US_SC_SCSI
,
US_PR_BULK
,
NULL
,
0
),
/* Reported by Miguel A. Fosas <amn3s1a@ono.com> */
UNUSUAL_DEV
(
0x0686
,
0x4017
,
0x0001
,
0x0001
,
"Minolta"
,
"DIMAGE E223"
,
US_SC_SCSI
,
US_PR_DEVICE
,
NULL
,
0
),
UNUSUAL_DEV
(
0x0693
,
0x0002
,
0x0100
,
0x0100
,
"Hagiwara"
,
"FlashGate SmartMedia"
,
...
...
@@ -607,7 +623,7 @@ UNUSUAL_DEV( 0x07c4, 0xa400, 0x0000, 0xffff,
UNUSUAL_DEV
(
0x07cf
,
0x1001
,
0x1000
,
0x9009
,
"Casio"
,
"QV DigitalCamera"
,
US_SC_
8070
,
US_PR_CB
,
NULL
,
US_SC_
DEVICE
,
US_PR_CB
,
NULL
,
US_FL_FIX_INQUIRY
),
/* Later Casio cameras apparently tell the truth */
...
...
@@ -633,15 +649,6 @@ UNUSUAL_DEV( 0x08ca, 0x2011, 0x0000, 0x9999,
US_SC_DEVICE
,
US_PR_DEVICE
,
NULL
,
US_FL_MODE_XLATE
),
/*Medion 6047 Digital Camera
Davide Andrian <_nessuno_@katamail.com>
*/
UNUSUAL_DEV
(
0x08ca
,
0x2011
,
0x0001
,
0x0001
,
"3MegaCam"
,
"3MegaCam"
,
US_SC_DEVICE
,
US_PR_BULK
,
NULL
,
US_FL_MODE_XLATE
),
/* Trumpion Microelectronics MP3 player (felipe_alfaro@linuxmail.org) */
UNUSUAL_DEV
(
0x090a
,
0x1200
,
0x0000
,
0x9999
,
"Trumpion"
,
...
...
@@ -720,6 +727,17 @@ UNUSUAL_DEV( 0x0d96, 0x5200, 0x0001, 0x0200,
"JD 5200 z3"
,
US_SC_DEVICE
,
US_PR_DEVICE
,
NULL
,
US_FL_FIX_INQUIRY
),
/* Reported by Lubomir Blaha <tritol@trilogic.cz>
* I _REALLY_ don't know what 3rd, 4th number and all defines mean, but this
* works for me. Can anybody correct these values? (I able to test corrected
* version.)
*/
UNUSUAL_DEV
(
0x0dd8
,
0x1060
,
0x0000
,
0xffff
,
"Netac"
,
"USB-CF-Card"
,
US_SC_DEVICE
,
US_PR_DEVICE
,
NULL
,
US_FL_FIX_INQUIRY
),
/* Submitted by Antoine Mairesse <antoine.mairesse@free.fr> */
UNUSUAL_DEV
(
0x0ed1
,
0x6660
,
0x0100
,
0x0300
,
"USB"
,
...
...
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