Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
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
Hide 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
;
transfer_length
=
(
count
-
writecount
);
if
(
transfer_length
>
USBLP_BUF_SIZE
)
transfer_length
=
USBLP_BUF_SIZE
;
if
(
writecount
==
count
)
{
up
(
&
usblp
->
sem
);
break
;
}
usblp
->
writeurb
->
transfer_buffer_length
=
transfer_length
;
usblp
->
writeurb
->
transfer_buffer_length
=
(
count
-
writecount
)
<
USBLP_BUF_SIZE
?
(
count
-
writecount
)
:
USBLP_BUF_SIZE
;
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
:
dev_dbg
(
hub_dev
,
"TT per port
\n
"
);
ret
=
usb_set_interface
(
dev
,
0
,
1
);
if
(
ret
==
0
)
{
dev_dbg
(
hub_dev
,
"TT per port
\n
"
);
hub
->
tt
.
multi
=
1
;
}
else
dev_err
(
hub_dev
,
"Using single TT (err %d)
\n
"
,
ret
);
hub
->
tt
.
hub
=
dev
;
hub
->
tt
.
multi
=
1
;
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,28 +625,62 @@ iso_stream_init (
buf1
=
0
;
}
multi
=
hb_mult
(
maxp
);
maxp
=
max_packet
(
maxp
);
buf1
|=
maxp
;
maxp
*=
multi
;
/* knows about ITD vs SITD */
if
(
dev
->
speed
==
USB_SPEED_HIGH
)
{
unsigned
multi
=
hb_mult
(
maxp
);
stream
->
dev
=
(
struct
hcd_dev
*
)
dev
->
hcpriv
;
stream
->
highspeed
=
1
;
stream
->
bEndpointAddress
=
is_input
|
epnum
;
stream
->
interval
=
interval
;
stream
->
maxp
=
maxp
;
maxp
=
max_packet
(
maxp
)
;
buf1
|=
maxp
;
maxp
*=
multi
;
stream
->
buf0
=
cpu_to_le32
((
epnum
<<
8
)
|
dev
->
devnum
);
stream
->
buf1
=
cpu_to_le32
(
buf1
);
stream
->
buf2
=
cpu_to_le32
(
multi
);
stream
->
buf0
=
cpu_to_le32
((
epnum
<<
8
)
|
dev
->
devnum
);
stream
->
buf1
=
cpu_to_le32
(
buf1
);
stream
->
buf2
=
cpu_to_le32
(
multi
);
/* usbfs wants to report the average usecs per frame tied up
* when transfers on this endpoint are scheduled ...
*/
stream
->
usecs
=
HS_USECS_ISO
(
maxp
);
bandwidth
=
stream
->
usecs
*
8
;
bandwidth
/=
1
<<
(
interval
-
1
);
/* usbfs wants to report the average usecs per frame tied up
* when transfers on this endpoint are scheduled ...
*/
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
...
...
@@ -595,22 +692,23 @@ iso_stream_put(struct ehci_hcd *ehci, struct ehci_iso_stream *stream)
* not like a QH -- no persistent state (toggle, halt)
*/
if
(
stream
->
refcount
==
1
)
{
int
is_in
;
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
;
}
/* we know urb->interval is 2^N uframes */
uframe
+=
urb
->
interval
;
}
while
(
uframe
!=
end
);
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
);
}
/* (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
);
q
=
*
q_p
;
break
;
}
*
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
;
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 */
...
...
@@ -492,22 +499,35 @@ struct ehci_sitd {
/* first part defined by EHCI spec */
u32
hw_next
;
/* 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_backpointer
;
/* see EHCI table 3-13 */
u32
hw_buf_hi
[
2
];
/* Appendix B */
u32
hw_fullspeed_ep
;
/* see EHCI table 3-9 */
u32
hw_uframe
;
/* see EHCI table 3-10 */
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,8 +645,9 @@ 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
,
ohci
->
hcca
,
ohci
->
hcca_dma
);
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
,
sizeof
*
ohci
->
hcca
,
&
ohci
->
hcca_dma
);
if
(
!
ohci
->
hcca
)
return
-
ENOMEM
;
}
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
);
if
(
!
ohci
->
hcca
)
return
-
ENOMEM
;
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,14 +268,12 @@ 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
);
if
(
!
ohci
->
hcca
)
return
-
ENOMEM
;
}
memset
(
ohci
->
hcca
,
0
,
sizeof
(
struct
ohci_hcca
));
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
)
{
ohci_stop
(
hcd
);
return
ret
;
...
...
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
,
sizeof
(
struct
uhci_td
),
16
,
0
);
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
,
sizeof
(
struct
uhci_qh
),
16
,
0
);
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
;
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
++
;
}
}
}
}
}
}
int
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,15 +2438,17 @@ 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
);
}
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
;
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
...
...
@@ -285,6 +294,13 @@ UNUSUAL_DEV( 0x054c, 0x0032, 0x0000, 0x9999,
"Memorystick MSC-U01N"
,
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"
,
...
...
@@ -414,6 +430,28 @@ UNUSUAL_DEV( 0x066b, 0x0105, 0x0100, 0x0100,
US_FL_SINGLE_LUN
),
#endif
/* Following three Minolta cameras reported by Martin Pool
* <mbp@sourcefrog.net>. Originally discovered by Kedar Petankar,
* Matthew Geier, Mikael Lofj"ard, Marcel de Boer.
*/
UNUSUAL_DEV
(
0x0686
,
0x4006
,
0x0001
,
0x0001
,
"Minolta"
,
"DiMAGE 7"
,
US_SC_SCSI
,
US_PR_DEVICE
,
NULL
,
0
),
UNUSUAL_DEV
(
0x0686
,
0x400b
,
0x0001
,
0x0001
,
"Minolta"
,
"DiMAGE 7i"
,
US_SC_SCSI
,
US_PR_DEVICE
,
NULL
,
0
),
UNUSUAL_DEV
(
0x0686
,
0x400f
,
0x0001
,
0x0001
,
"Minolta"
,
"DiMAGE 7Hi"
,
US_SC_SCSI
,
US_PR_DEVICE
,
NULL
,
0
),
/* Submitted by Benny Sjostrand <benny@hostmobility.com> */
UNUSUAL_DEV
(
0x0686
,
0x4011
,
0x0001
,
0x0001
,
"Minolta"
,
...
...
@@ -426,28 +464,6 @@ UNUSUAL_DEV( 0x0686, 0x4017, 0x0001, 0x0001,
"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.
*/
UNUSUAL_DEV
(
0x0686
,
0x4006
,
0x0001
,
0x0001
,
"Minolta"
,
"DiMAGE 7"
,
US_SC_SCSI
,
US_PR_DEVICE
,
NULL
,
0
),
UNUSUAL_DEV
(
0x0686
,
0x400b
,
0x0001
,
0x0001
,
"Minolta"
,
"DiMAGE 7i"
,
US_SC_SCSI
,
US_PR_DEVICE
,
NULL
,
0
),
UNUSUAL_DEV
(
0x0686
,
0x400f
,
0x0001
,
0x0001
,
"Minolta"
,
"DiMAGE 7Hi"
,
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