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