Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
1a569433
Commit
1a569433
authored
May 23, 2003
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge
bk://kernel.bkbits.net/gregkh/linux/linus-2.5
into penguin.transmeta.com:/home/torvalds/v2.5/linux
parents
47e4079c
85b55d6f
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
522 additions
and
472 deletions
+522
-472
drivers/usb/core/message.c
drivers/usb/core/message.c
+3
-1
drivers/usb/gadget/ether.c
drivers/usb/gadget/ether.c
+1
-1
drivers/usb/gadget/net2280.c
drivers/usb/gadget/net2280.c
+53
-43
drivers/usb/gadget/net2280.h
drivers/usb/gadget/net2280.h
+9
-0
drivers/usb/gadget/zero.c
drivers/usb/gadget/zero.c
+2
-5
drivers/usb/host/uhci-hcd.c
drivers/usb/host/uhci-hcd.c
+130
-34
drivers/usb/host/uhci-hcd.h
drivers/usb/host/uhci-hcd.h
+28
-1
drivers/usb/misc/speedtch.c
drivers/usb/misc/speedtch.c
+293
-386
drivers/usb/storage/transport.c
drivers/usb/storage/transport.c
+1
-1
drivers/usb/storage/transport.h
drivers/usb/storage/transport.h
+2
-0
No files found.
drivers/usb/core/message.c
View file @
1a569433
...
@@ -672,6 +672,7 @@ void usb_set_maxpacket(struct usb_device *dev)
...
@@ -672,6 +672,7 @@ void usb_set_maxpacket(struct usb_device *dev)
{
{
int
i
,
b
;
int
i
,
b
;
/* NOTE: affects all endpoints _except_ ep0 */
for
(
i
=
0
;
i
<
dev
->
actconfig
->
desc
.
bNumInterfaces
;
i
++
)
{
for
(
i
=
0
;
i
<
dev
->
actconfig
->
desc
.
bNumInterfaces
;
i
++
)
{
struct
usb_interface
*
ifp
=
dev
->
actconfig
->
interface
+
i
;
struct
usb_interface
*
ifp
=
dev
->
actconfig
->
interface
+
i
;
struct
usb_host_interface
*
as
=
ifp
->
altsetting
+
ifp
->
act_altsetting
;
struct
usb_host_interface
*
as
=
ifp
->
altsetting
+
ifp
->
act_altsetting
;
...
@@ -862,6 +863,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
...
@@ -862,6 +863,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
usb_settoggle
(
dev
,
ep
,
out
,
0
);
usb_settoggle
(
dev
,
ep
,
out
,
0
);
(
out
?
dev
->
epmaxpacketout
:
dev
->
epmaxpacketin
)
[
ep
]
(
out
?
dev
->
epmaxpacketout
:
dev
->
epmaxpacketin
)
[
ep
]
=
iface_as
->
endpoint
[
i
].
desc
.
wMaxPacketSize
;
=
iface_as
->
endpoint
[
i
].
desc
.
wMaxPacketSize
;
usb_endpoint_running
(
dev
,
ep
,
out
);
}
}
return
0
;
return
0
;
...
@@ -916,7 +918,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
...
@@ -916,7 +918,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
/* if it's already configured, clear out old state first. */
/* if it's already configured, clear out old state first. */
if
(
dev
->
state
!=
USB_STATE_ADDRESS
&&
disable
)
{
if
(
dev
->
state
!=
USB_STATE_ADDRESS
&&
disable
)
{
for
(
i
=
0
;
i
<
15
;
i
++
)
{
for
(
i
=
1
/* skip ep0 */
;
i
<
15
;
i
++
)
{
disable
(
dev
,
i
);
disable
(
dev
,
i
);
disable
(
dev
,
USB_DIR_IN
|
i
);
disable
(
dev
,
USB_DIR_IN
|
i
);
}
}
...
...
drivers/usb/gadget/ether.c
View file @
1a569433
...
@@ -1107,7 +1107,7 @@ eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
...
@@ -1107,7 +1107,7 @@ eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
}
}
/* respond with data transfer before status phase? */
/* respond with data transfer before status phase? */
if
(
value
>
0
)
{
if
(
value
>
=
0
)
{
req
->
length
=
value
;
req
->
length
=
value
;
value
=
usb_ep_queue
(
gadget
->
ep0
,
req
,
GFP_ATOMIC
);
value
=
usb_ep_queue
(
gadget
->
ep0
,
req
,
GFP_ATOMIC
);
if
(
value
<
0
)
{
if
(
value
<
0
)
{
...
...
drivers/usb/gadget/net2280.c
View file @
1a569433
...
@@ -393,7 +393,7 @@ net2280_free_request (struct usb_ep *_ep, struct usb_request *_req)
...
@@ -393,7 +393,7 @@ net2280_free_request (struct usb_ep *_ep, struct usb_request *_req)
struct
net2280_request
*
req
;
struct
net2280_request
*
req
;
ep
=
container_of
(
_ep
,
struct
net2280_ep
,
ep
);
ep
=
container_of
(
_ep
,
struct
net2280_ep
,
ep
);
if
(
!
ep
||
!
_req
)
if
(
!
_
ep
||
!
_req
)
return
;
return
;
req
=
container_of
(
_req
,
struct
net2280_request
,
req
);
req
=
container_of
(
_req
,
struct
net2280_request
,
req
);
...
@@ -442,7 +442,7 @@ net2280_alloc_buffer (
...
@@ -442,7 +442,7 @@ net2280_alloc_buffer (
struct
net2280_ep
*
ep
;
struct
net2280_ep
*
ep
;
ep
=
container_of
(
_ep
,
struct
net2280_ep
,
ep
);
ep
=
container_of
(
_ep
,
struct
net2280_ep
,
ep
);
if
(
!
ep
||
(
!
ep
->
desc
&&
ep
->
num
!=
0
))
if
(
!
_
ep
||
(
!
ep
->
desc
&&
ep
->
num
!=
0
))
return
0
;
return
0
;
*
dma
=
DMA_ADDR_INVALID
;
*
dma
=
DMA_ADDR_INVALID
;
...
@@ -561,16 +561,12 @@ static void out_flush (struct net2280_ep *ep)
...
@@ -561,16 +561,12 @@ static void out_flush (struct net2280_ep *ep)
writel
((
1
<<
FIFO_FLUSH
),
statp
);
writel
((
1
<<
FIFO_FLUSH
),
statp
);
mb
();
mb
();
tmp
=
readl
(
statp
);
tmp
=
readl
(
statp
);
if
(
tmp
&
(
1
<<
DATA_OUT_PING_TOKEN_INTERRUPT
))
{
if
(
tmp
&
(
1
<<
DATA_OUT_PING_TOKEN_INTERRUPT
)
/* high speed did bulk NYET; fifo isn't filling */
&&
ep
->
dev
->
gadget
.
speed
==
USB_SPEED_FULL
)
{
unsigned
usec
;
unsigned
usec
;
if
(
ep
->
dev
->
gadget
.
speed
==
USB_SPEED_HIGH
)
{
usec
=
50
;
/* 64 byte bulk/interrupt */
if
(
ep
->
ep
.
maxpacket
<=
512
)
usec
=
10
;
/* 512 byte bulk */
else
usec
=
21
;
/* 1024 byte interrupt */
}
else
usec
=
50
;
/* 64 byte bulk/interrupt */
handshake
(
statp
,
(
1
<<
USB_OUT_PING_NAK_SENT
),
handshake
(
statp
,
(
1
<<
USB_OUT_PING_NAK_SENT
),
(
1
<<
USB_OUT_PING_NAK_SENT
),
usec
);
(
1
<<
USB_OUT_PING_NAK_SENT
),
usec
);
/* NAK done; now CLEAR_NAK_OUT_PACKETS is safe */
/* NAK done; now CLEAR_NAK_OUT_PACKETS is safe */
...
@@ -614,15 +610,13 @@ read_fifo (struct net2280_ep *ep, struct net2280_request *req)
...
@@ -614,15 +610,13 @@ read_fifo (struct net2280_ep *ep, struct net2280_request *req)
count
=
readl
(
&
regs
->
ep_avail
);
count
=
readl
(
&
regs
->
ep_avail
);
tmp
=
req
->
req
.
length
-
req
->
req
.
actual
;
tmp
=
req
->
req
.
length
-
req
->
req
.
actual
;
if
(
count
>
tmp
)
{
if
(
count
>
tmp
)
{
unsigned
over
=
tmp
%
ep
->
ep
.
maxpacket
;
/* as with DMA, data overflow gets flushed */
if
((
tmp
%
ep
->
ep
.
maxpacket
)
!=
0
)
{
/* FIXME handle this consistently between PIO and DMA */
if
(
over
)
{
ERROR
(
ep
->
dev
,
ERROR
(
ep
->
dev
,
"%s out fifo %d bytes,
over %d extra
%d
\n
"
,
"%s out fifo %d bytes,
expected
%d
\n
"
,
ep
->
ep
.
name
,
count
,
over
,
count
-
tmp
);
ep
->
ep
.
name
,
count
,
tmp
);
req
->
req
.
status
=
-
EOVERFLOW
;
req
->
req
.
status
=
-
EOVERFLOW
;
tmp
-=
over
;
cleanup
=
1
;
}
}
count
=
tmp
;
count
=
tmp
;
}
}
...
@@ -670,10 +664,12 @@ fill_dma_desc (struct net2280_ep *ep, struct net2280_request *req, int valid)
...
@@ -670,10 +664,12 @@ fill_dma_desc (struct net2280_ep *ep, struct net2280_request *req, int valid)
/* don't let DMA continue after a short OUT packet,
/* don't let DMA continue after a short OUT packet,
* so overruns can't affect the next transfer.
* so overruns can't affect the next transfer.
* in case of overruns on max-size packets, we can't
* stop the fifo from filling but we can flush it.
*/
*/
if
(
ep
->
is_in
)
if
(
ep
->
is_in
)
dmacount
|=
(
1
<<
DMA_DIRECTION
);
dmacount
|=
(
1
<<
DMA_DIRECTION
);
else
if
((
dmacount
%
ep
->
ep
.
maxpacket
)
!=
0
)
else
dmacount
|=
(
1
<<
END_OF_CHAIN
);
dmacount
|=
(
1
<<
END_OF_CHAIN
);
req
->
valid
=
valid
;
req
->
valid
=
valid
;
...
@@ -897,8 +893,12 @@ net2280_queue (struct usb_ep *_ep, struct usb_request *_req, int gfp_flags)
...
@@ -897,8 +893,12 @@ net2280_queue (struct usb_ep *_ep, struct usb_request *_req, int gfp_flags)
start_dma
(
ep
,
req
);
start_dma
(
ep
,
req
);
else
{
else
{
/* maybe there's no control data, just status ack */
/* maybe there's no control data, just status ack */
if
(
ep
->
num
==
0
&&
_req
->
length
==
0
)
if
(
ep
->
num
==
0
&&
_req
->
length
==
0
)
{
allow_status
(
ep
);
done
(
ep
,
req
,
0
);
VDEBUG
(
dev
,
"%s status ack
\n
"
,
ep
->
ep
.
name
);
goto
done
;
goto
done
;
}
/* PIO ... stuff the fifo, or unblock it. */
/* PIO ... stuff the fifo, or unblock it. */
if
(
ep
->
is_in
)
if
(
ep
->
is_in
)
...
@@ -948,10 +948,9 @@ net2280_queue (struct usb_ep *_ep, struct usb_request *_req, int gfp_flags)
...
@@ -948,10 +948,9 @@ net2280_queue (struct usb_ep *_ep, struct usb_request *_req, int gfp_flags)
}
/* else the irq handler advances the queue. */
}
/* else the irq handler advances the queue. */
if
(
req
)
{
if
(
req
)
done:
list_add_tail
(
&
req
->
queue
,
&
ep
->
queue
);
list_add_tail
(
&
req
->
queue
,
&
ep
->
queue
);
}
done:
spin_unlock_irqrestore
(
&
dev
->
lock
,
flags
);
spin_unlock_irqrestore
(
&
dev
->
lock
,
flags
);
/* pci writes may still be posted */
/* pci writes may still be posted */
...
@@ -992,6 +991,8 @@ static void scan_dma_completions (struct net2280_ep *ep)
...
@@ -992,6 +991,8 @@ static void scan_dma_completions (struct net2280_ep *ep)
/* SHORT_PACKET_TRANSFERRED_INTERRUPT handles "usb-short"
/* SHORT_PACKET_TRANSFERRED_INTERRUPT handles "usb-short"
* packets, including overruns, even when the transfer was
* packets, including overruns, even when the transfer was
* exactly the length requested (dmacount now zero).
* exactly the length requested (dmacount now zero).
* FIXME there's an overrun case here too, where we expect
* a short packet but receive a max length one (won't NAK).
*/
*/
if
(
!
ep
->
is_in
&&
(
req
->
req
.
length
%
ep
->
ep
.
maxpacket
)
!=
0
)
{
if
(
!
ep
->
is_in
&&
(
req
->
req
.
length
%
ep
->
ep
.
maxpacket
)
!=
0
)
{
req
->
dma_done
=
1
;
req
->
dma_done
=
1
;
...
@@ -1186,7 +1187,8 @@ net2280_set_halt (struct usb_ep *_ep, int value)
...
@@ -1186,7 +1187,8 @@ net2280_set_halt (struct usb_ep *_ep, int value)
return
-
EINVAL
;
return
-
EINVAL
;
if
(
!
ep
->
dev
->
driver
||
ep
->
dev
->
gadget
.
speed
==
USB_SPEED_UNKNOWN
)
if
(
!
ep
->
dev
->
driver
||
ep
->
dev
->
gadget
.
speed
==
USB_SPEED_UNKNOWN
)
return
-
ESHUTDOWN
;
return
-
ESHUTDOWN
;
if
((
ep
->
desc
->
bmAttributes
&
0x03
)
==
USB_ENDPOINT_XFER_ISOC
)
if
(
ep
->
desc
/* not ep0 */
&&
(
ep
->
desc
->
bmAttributes
&
0x03
)
==
USB_ENDPOINT_XFER_ISOC
)
return
-
EINVAL
;
return
-
EINVAL
;
VDEBUG
(
ep
->
dev
,
"%s %s halt
\n
"
,
_ep
->
name
,
value
?
"set"
:
"clear"
);
VDEBUG
(
ep
->
dev
,
"%s %s halt
\n
"
,
_ep
->
name
,
value
?
"set"
:
"clear"
);
...
@@ -1712,7 +1714,7 @@ static void usb_reinit (struct net2280 *dev)
...
@@ -1712,7 +1714,7 @@ static void usb_reinit (struct net2280 *dev)
static
void
ep0_start
(
struct
net2280
*
dev
)
static
void
ep0_start
(
struct
net2280
*
dev
)
{
{
writel
(
(
1
<<
SET
_EP_HIDE_STATUS_PHASE
)
writel
(
(
1
<<
CLEAR
_EP_HIDE_STATUS_PHASE
)
|
(
1
<<
CLEAR_NAK_OUT_PACKETS
)
|
(
1
<<
CLEAR_NAK_OUT_PACKETS
)
|
(
1
<<
CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE
)
|
(
1
<<
CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE
)
,
&
dev
->
epregs
[
0
].
ep_rsp
);
,
&
dev
->
epregs
[
0
].
ep_rsp
);
...
@@ -1916,22 +1918,27 @@ static void handle_ep_small (struct net2280_ep *ep)
...
@@ -1916,22 +1918,27 @@ static void handle_ep_small (struct net2280_ep *ep)
if
(
ep
->
is_in
)
{
if
(
ep
->
is_in
)
{
/* status; stop NAKing */
/* status; stop NAKing */
if
(
t
&
(
1
<<
DATA_OUT_PING_TOKEN_INTERRUPT
))
{
if
(
t
&
(
1
<<
DATA_OUT_PING_TOKEN_INTERRUPT
))
{
if
(
ep
->
dev
->
protocol_stall
)
if
(
ep
->
dev
->
protocol_stall
)
{
ep
->
stopped
=
1
;
set_halt
(
ep
);
set_halt
(
ep
);
}
mode
=
2
;
mode
=
2
;
/* reply to extra IN tokens with a zlp */
/* reply to extra IN
data
tokens with a zlp */
}
else
if
(
t
&
(
1
<<
DATA_IN_TOKEN_INTERRUPT
))
{
}
else
if
(
t
&
(
1
<<
DATA_IN_TOKEN_INTERRUPT
))
{
if
(
ep
->
dev
->
protocol_stall
)
{
if
(
ep
->
dev
->
protocol_stall
)
{
ep
->
stopped
=
1
;
set_halt
(
ep
);
set_halt
(
ep
);
mode
=
2
;
mode
=
2
;
}
else
if
(
!
req
)
}
else
if
(
!
req
&&
ep
->
stopped
)
write_fifo
(
ep
,
0
);
write_fifo
(
ep
,
0
);
}
}
}
else
{
}
else
{
/* status; stop NAKing */
/* status; stop NAKing */
if
(
t
&
(
1
<<
DATA_IN_TOKEN_INTERRUPT
))
{
if
(
t
&
(
1
<<
DATA_IN_TOKEN_INTERRUPT
))
{
if
(
ep
->
dev
->
protocol_stall
)
if
(
ep
->
dev
->
protocol_stall
)
{
ep
->
stopped
=
1
;
set_halt
(
ep
);
set_halt
(
ep
);
}
mode
=
2
;
mode
=
2
;
/* an extra OUT token is an error */
/* an extra OUT token is an error */
}
else
if
(((
t
&
(
1
<<
DATA_OUT_PING_TOKEN_INTERRUPT
))
}
else
if
(((
t
&
(
1
<<
DATA_OUT_PING_TOKEN_INTERRUPT
))
...
@@ -2031,6 +2038,10 @@ static void handle_ep_small (struct net2280_ep *ep)
...
@@ -2031,6 +2038,10 @@ static void handle_ep_small (struct net2280_ep *ep)
/* maybe advance queue to next request */
/* maybe advance queue to next request */
if
(
ep
->
num
==
0
)
{
if
(
ep
->
num
==
0
)
{
/* FIXME need mechanism (request flag?) so control OUT
* can decide to stall ep0 after that done() returns,
* from non-irq context
*/
allow_status
(
ep
);
allow_status
(
ep
);
req
=
0
;
req
=
0
;
}
else
{
}
else
{
...
@@ -2171,6 +2182,7 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
...
@@ -2171,6 +2182,7 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
struct
net2280_ep
*
e
;
struct
net2280_ep
*
e
;
u16
status
;
u16
status
;
/* hw handles device and interface status */
if
(
u
.
r
.
bRequestType
!=
(
USB_DIR_IN
|
USB_RECIP_ENDPOINT
))
if
(
u
.
r
.
bRequestType
!=
(
USB_DIR_IN
|
USB_RECIP_ENDPOINT
))
goto
delegate
;
goto
delegate
;
if
((
e
=
get_ep_by_addr
(
dev
,
u
.
r
.
wIndex
))
==
0
if
((
e
=
get_ep_by_addr
(
dev
,
u
.
r
.
wIndex
))
==
0
...
@@ -2188,12 +2200,14 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
...
@@ -2188,12 +2200,14 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
set_fifo_bytecount
(
ep
,
u
.
r
.
wLength
);
set_fifo_bytecount
(
ep
,
u
.
r
.
wLength
);
writel
(
status
,
&
dev
->
epregs
[
0
].
ep_data
);
writel
(
status
,
&
dev
->
epregs
[
0
].
ep_data
);
allow_status
(
ep
);
allow_status
(
ep
);
VDEBUG
(
dev
,
"%s stat %02x
\n
"
,
ep
->
ep
.
name
,
status
);
goto
next_endpoints
;
goto
next_endpoints
;
}
}
break
;
break
;
case
USB_REQ_CLEAR_FEATURE
:
{
case
USB_REQ_CLEAR_FEATURE
:
{
struct
net2280_ep
*
e
;
struct
net2280_ep
*
e
;
/* hw handles device features */
if
(
u
.
r
.
bRequestType
!=
USB_RECIP_ENDPOINT
)
if
(
u
.
r
.
bRequestType
!=
USB_RECIP_ENDPOINT
)
goto
delegate
;
goto
delegate
;
if
(
u
.
r
.
wIndex
!=
0
/* HALT feature */
if
(
u
.
r
.
wIndex
!=
0
/* HALT feature */
...
@@ -2202,11 +2216,15 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
...
@@ -2202,11 +2216,15 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
if
((
e
=
get_ep_by_addr
(
dev
,
u
.
r
.
wIndex
))
==
0
)
if
((
e
=
get_ep_by_addr
(
dev
,
u
.
r
.
wIndex
))
==
0
)
goto
do_stall
;
goto
do_stall
;
clear_halt
(
e
);
clear_halt
(
e
);
allow_status
(
ep
);
VDEBUG
(
dev
,
"%s clear halt
\n
"
,
ep
->
ep
.
name
);
goto
next_endpoints
;
}
}
break
;
break
;
case
USB_REQ_SET_FEATURE
:
{
case
USB_REQ_SET_FEATURE
:
{
struct
net2280_ep
*
e
;
struct
net2280_ep
*
e
;
/* hw handles device features */
if
(
u
.
r
.
bRequestType
!=
USB_RECIP_ENDPOINT
)
if
(
u
.
r
.
bRequestType
!=
USB_RECIP_ENDPOINT
)
goto
delegate
;
goto
delegate
;
if
(
u
.
r
.
wIndex
!=
0
/* HALT feature */
if
(
u
.
r
.
wIndex
!=
0
/* HALT feature */
...
@@ -2215,6 +2233,9 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
...
@@ -2215,6 +2233,9 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
if
((
e
=
get_ep_by_addr
(
dev
,
u
.
r
.
wIndex
))
==
0
)
if
((
e
=
get_ep_by_addr
(
dev
,
u
.
r
.
wIndex
))
==
0
)
goto
do_stall
;
goto
do_stall
;
set_halt
(
e
);
set_halt
(
e
);
allow_status
(
ep
);
VDEBUG
(
dev
,
"%s set halt
\n
"
,
ep
->
ep
.
name
);
goto
next_endpoints
;
}
}
break
;
break
;
default:
default:
...
@@ -2235,23 +2256,12 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
...
@@ -2235,23 +2256,12 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
VDEBUG
(
dev
,
"req %02x.%02x protocol STALL; stat %d
\n
"
,
VDEBUG
(
dev
,
"req %02x.%02x protocol STALL; stat %d
\n
"
,
u
.
r
.
bRequestType
,
u
.
r
.
bRequest
,
tmp
);
u
.
r
.
bRequestType
,
u
.
r
.
bRequest
,
tmp
);
dev
->
protocol_stall
=
1
;
dev
->
protocol_stall
=
1
;
/* when there's no data, queueing a response is optional */
}
else
if
(
list_empty
(
&
ep
->
queue
))
{
if
(
u
.
r
.
wLength
==
0
)
{
/* done() not possible/requested */
allow_status
(
ep
);
}
else
{
DEBUG
(
dev
,
"req %02x.%02x v%04x "
"gadget error, len %d, stat %d
\n
"
,
u
.
r
.
bRequestType
,
u
.
r
.
bRequest
,
le16_to_cpu
(
u
.
r
.
wValue
),
u
.
r
.
wLength
,
tmp
);
dev
->
protocol_stall
=
1
;
}
}
}
/* some in/out token irq should follow; maybe stall then. */
/* some in/out token irq should follow; maybe stall then.
* driver must queue a request (even zlp) or halt ep0
* before the host times out.
*/
}
}
next_endpoints:
next_endpoints:
...
...
drivers/usb/gadget/net2280.h
View file @
1a569433
...
@@ -437,6 +437,8 @@ struct net2280_ep_regs { /* [11.9] */
...
@@ -437,6 +437,8 @@ struct net2280_ep_regs { /* [11.9] */
/*-------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------*/
#ifdef __KERNEL__
/* indexed registers [11.10] are accessed indirectly
/* indexed registers [11.10] are accessed indirectly
* caller must own the device lock.
* caller must own the device lock.
*/
*/
...
@@ -457,6 +459,9 @@ set_idx_reg (struct net2280_regs *regs, u32 index, u32 value)
...
@@ -457,6 +459,9 @@ set_idx_reg (struct net2280_regs *regs, u32 index, u32 value)
/* posted, may not be visible yet */
/* posted, may not be visible yet */
}
}
#endif
/* __KERNEL__ */
#define REG_DIAG 0x0
#define REG_DIAG 0x0
#define RETRY_COUNTER 16
#define RETRY_COUNTER 16
#define FORCE_PCI_SERR 11
#define FORCE_PCI_SERR 11
...
@@ -471,6 +476,8 @@ set_idx_reg (struct net2280_regs *regs, u32 index, u32 value)
...
@@ -471,6 +476,8 @@ set_idx_reg (struct net2280_regs *regs, u32 index, u32 value)
#define REG_CHIPREV 0x03
/* in bcd */
#define REG_CHIPREV 0x03
/* in bcd */
#define REG_HS_NAK_RATE 0x0a
/* NAK per N uframes */
#define REG_HS_NAK_RATE 0x0a
/* NAK per N uframes */
#ifdef __KERNEL__
/* ep a-f highspeed and fullspeed maxpacket, addresses
/* ep a-f highspeed and fullspeed maxpacket, addresses
* computed from ep->num
* computed from ep->num
*/
*/
...
@@ -519,6 +526,7 @@ static inline void allow_status (struct net2280_ep *ep)
...
@@ -519,6 +526,7 @@ static inline void allow_status (struct net2280_ep *ep)
writel
(
(
1
<<
CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE
)
writel
(
(
1
<<
CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE
)
|
(
1
<<
CLEAR_NAK_OUT_PACKETS_MODE
)
|
(
1
<<
CLEAR_NAK_OUT_PACKETS_MODE
)
,
&
ep
->
regs
->
ep_rsp
);
,
&
ep
->
regs
->
ep_rsp
);
ep
->
stopped
=
1
;
}
}
static
inline
void
set_halt
(
struct
net2280_ep
*
ep
)
static
inline
void
set_halt
(
struct
net2280_ep
*
ep
)
...
@@ -707,3 +715,4 @@ static inline void stop_out_naking (struct net2280_ep *ep)
...
@@ -707,3 +715,4 @@ static inline void stop_out_naking (struct net2280_ep *ep)
writel
((
1
<<
CLEAR_NAK_OUT_PACKETS
),
&
ep
->
regs
->
ep_rsp
);
writel
((
1
<<
CLEAR_NAK_OUT_PACKETS
),
&
ep
->
regs
->
ep_rsp
);
}
}
#endif
/* __KERNEL__ */
drivers/usb/gadget/zero.c
View file @
1a569433
...
@@ -653,7 +653,7 @@ static void source_sink_complete (struct usb_ep *ep, struct usb_request *req)
...
@@ -653,7 +653,7 @@ static void source_sink_complete (struct usb_ep *ep, struct usb_request *req)
/* this endpoint is normally active while we're configured */
/* this endpoint is normally active while we're configured */
case
-
ECONNRESET
:
/* request dequeued */
case
-
ECONNRESET
:
/* request dequeued */
case
-
ESHUTDOWN
:
/* disconnect from host */
case
-
ESHUTDOWN
:
/* disconnect from host */
DEBUG
(
dev
,
"%s gone (%d), %d/%d
\n
"
,
ep
->
name
,
status
,
V
DEBUG
(
dev
,
"%s gone (%d), %d/%d
\n
"
,
ep
->
name
,
status
,
req
->
actual
,
req
->
length
);
req
->
actual
,
req
->
length
);
free_ep_req
(
ep
,
req
);
free_ep_req
(
ep
,
req
);
return
;
return
;
...
@@ -1035,9 +1035,6 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
...
@@ -1035,9 +1035,6 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
if
(
ctrl
->
bRequestType
!=
0
)
if
(
ctrl
->
bRequestType
!=
0
)
break
;
break
;
spin_lock
(
&
dev
->
lock
);
spin_lock
(
&
dev
->
lock
);
/* change hardware configuration!
* no response queued, just zero status == success
*/
value
=
zero_set_config
(
dev
,
ctrl
->
wValue
,
GFP_ATOMIC
);
value
=
zero_set_config
(
dev
,
ctrl
->
wValue
,
GFP_ATOMIC
);
spin_unlock
(
&
dev
->
lock
);
spin_unlock
(
&
dev
->
lock
);
break
;
break
;
...
@@ -1092,7 +1089,7 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
...
@@ -1092,7 +1089,7 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
}
}
/* respond with data transfer before status phase? */
/* respond with data transfer before status phase? */
if
(
value
>
0
)
{
if
(
value
>
=
0
)
{
req
->
length
=
value
;
req
->
length
=
value
;
value
=
usb_ep_queue
(
gadget
->
ep0
,
req
,
GFP_ATOMIC
);
value
=
usb_ep_queue
(
gadget
->
ep0
,
req
,
GFP_ATOMIC
);
if
(
value
<
0
)
{
if
(
value
<
0
)
{
...
...
drivers/usb/host/uhci-hcd.c
View file @
1a569433
...
@@ -61,7 +61,7 @@
...
@@ -61,7 +61,7 @@
/*
/*
* Version Information
* Version Information
*/
*/
#define DRIVER_VERSION "v2.
0
"
#define DRIVER_VERSION "v2.
1
"
#define DRIVER_AUTHOR "Linus 'Frodo Rabbit' Torvalds, Johannes Erdfelt, Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber"
#define DRIVER_AUTHOR "Linus 'Frodo Rabbit' Torvalds, Johannes Erdfelt, Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber"
#define DRIVER_DESC "USB Universal Host Controller Interface driver"
#define DRIVER_DESC "USB Universal Host Controller Interface driver"
...
@@ -91,9 +91,7 @@ static int uhci_get_current_frame_number(struct uhci_hcd *uhci);
...
@@ -91,9 +91,7 @@ static int uhci_get_current_frame_number(struct uhci_hcd *uhci);
static
int
uhci_urb_dequeue
(
struct
usb_hcd
*
hcd
,
struct
urb
*
urb
);
static
int
uhci_urb_dequeue
(
struct
usb_hcd
*
hcd
,
struct
urb
*
urb
);
static
void
uhci_unlink_generic
(
struct
uhci_hcd
*
uhci
,
struct
urb
*
urb
);
static
void
uhci_unlink_generic
(
struct
uhci_hcd
*
uhci
,
struct
urb
*
urb
);
static
int
ports_active
(
struct
uhci_hcd
*
uhci
);
static
void
hc_state_transitions
(
struct
uhci_hcd
*
uhci
);
static
void
suspend_hc
(
struct
uhci_hcd
*
uhci
);
static
void
wakeup_hc
(
struct
uhci_hcd
*
uhci
);
/* If a transfer is still active after this much time, turn off FSBR */
/* If a transfer is still active after this much time, turn off FSBR */
#define IDLE_TIMEOUT (HZ / 20)
/* 50 ms */
#define IDLE_TIMEOUT (HZ / 20)
/* 50 ms */
...
@@ -1757,9 +1755,8 @@ static void stall_callback(unsigned long ptr)
...
@@ -1757,9 +1755,8 @@ static void stall_callback(unsigned long ptr)
uhci
->
skel_term_qh
->
link
=
UHCI_PTR_TERM
;
uhci
->
skel_term_qh
->
link
=
UHCI_PTR_TERM
;
}
}
/* enter global suspend if nothing connected */
/* Poll for and perform state transitions */
if
(
!
uhci
->
is_suspended
&&
!
ports_active
(
uhci
))
hc_state_transitions
(
uhci
);
suspend_hc
(
uhci
);
init_stall_timer
(
hcd
);
init_stall_timer
(
hcd
);
}
}
...
@@ -1884,14 +1881,14 @@ static void uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
...
@@ -1884,14 +1881,14 @@ static void uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
err
(
"%x: host system error, PCI problems?"
,
io_addr
);
err
(
"%x: host system error, PCI problems?"
,
io_addr
);
if
(
status
&
USBSTS_HCPE
)
if
(
status
&
USBSTS_HCPE
)
err
(
"%x: host controller process error. something bad happened"
,
io_addr
);
err
(
"%x: host controller process error. something bad happened"
,
io_addr
);
if
((
status
&
USBSTS_HCH
)
&&
!
uhci
->
is_suspended
)
{
if
((
status
&
USBSTS_HCH
)
&&
uhci
->
state
>
0
)
{
err
(
"%x: host controller halted. very bad"
,
io_addr
);
err
(
"%x: host controller halted. very bad"
,
io_addr
);
/* FIXME: Reset the controller, fix the offending TD */
/* FIXME: Reset the controller, fix the offending TD */
}
}
}
}
if
(
status
&
USBSTS_RD
)
if
(
status
&
USBSTS_RD
)
wakeup_hc
(
uhci
)
;
uhci
->
resume_detect
=
1
;
uhci_free_pending_qhs
(
uhci
);
uhci_free_pending_qhs
(
uhci
);
...
@@ -1922,10 +1919,18 @@ static void reset_hc(struct uhci_hcd *uhci)
...
@@ -1922,10 +1919,18 @@ static void reset_hc(struct uhci_hcd *uhci)
unsigned
int
io_addr
=
uhci
->
io_addr
;
unsigned
int
io_addr
=
uhci
->
io_addr
;
/* Global reset for 50ms */
/* Global reset for 50ms */
uhci
->
state
=
UHCI_RESET
;
outw
(
USBCMD_GRESET
,
io_addr
+
USBCMD
);
outw
(
USBCMD_GRESET
,
io_addr
+
USBCMD
);
wait_ms
(
50
);
set_current_state
(
TASK_UNINTERRUPTIBLE
);
schedule_timeout
((
HZ
*
50
+
999
)
/
1000
);
set_current_state
(
TASK_RUNNING
);
outw
(
0
,
io_addr
+
USBCMD
);
outw
(
0
,
io_addr
+
USBCMD
);
wait_ms
(
10
);
/* Another 10ms delay */
set_current_state
(
TASK_UNINTERRUPTIBLE
);
schedule_timeout
((
HZ
*
10
+
999
)
/
1000
);
set_current_state
(
TASK_RUNNING
);
uhci
->
resume_detect
=
0
;
}
}
static
void
suspend_hc
(
struct
uhci_hcd
*
uhci
)
static
void
suspend_hc
(
struct
uhci_hcd
*
uhci
)
...
@@ -1933,34 +1938,49 @@ static void suspend_hc(struct uhci_hcd *uhci)
...
@@ -1933,34 +1938,49 @@ static void suspend_hc(struct uhci_hcd *uhci)
unsigned
int
io_addr
=
uhci
->
io_addr
;
unsigned
int
io_addr
=
uhci
->
io_addr
;
dbg
(
"%x: suspend_hc"
,
io_addr
);
dbg
(
"%x: suspend_hc"
,
io_addr
);
uhci
->
state
=
UHCI_SUSPENDED
;
uhci
->
is_suspended
=
1
;
uhci
->
resume_detect
=
0
;
smp_wmb
();
outw
(
USBCMD_EGSM
,
io_addr
+
USBCMD
);
outw
(
USBCMD_EGSM
,
io_addr
+
USBCMD
);
}
}
static
void
wakeup_hc
(
struct
uhci_hcd
*
uhci
)
static
void
wakeup_hc
(
struct
uhci_hcd
*
uhci
)
{
{
unsigned
int
io_addr
=
uhci
->
io_addr
;
unsigned
int
io_addr
=
uhci
->
io_addr
;
unsigned
int
status
;
dbg
(
"%x: wakeup_hc"
,
io_addr
);
switch
(
uhci
->
state
)
{
case
UHCI_SUSPENDED
:
/* Start the resume */
dbg
(
"%x: wakeup_hc"
,
io_addr
);
/* Global resume for 20ms */
/* Global resume for >= 20ms */
outw
(
USBCMD_FGR
|
USBCMD_EGSM
,
io_addr
+
USBCMD
);
outw
(
USBCMD_FGR
|
USBCMD_EGSM
,
io_addr
+
USBCMD
);
wait_ms
(
20
);
uhci
->
state
=
UHCI_RESUMING_1
;
outw
(
0
,
io_addr
+
USBCMD
);
uhci
->
state_end
=
jiffies
+
(
20
*
HZ
+
999
)
/
1000
;
break
;
/* wait for EOP to be sent */
status
=
inw
(
io_addr
+
USBCMD
);
while
(
status
&
USBCMD_FGR
)
status
=
inw
(
io_addr
+
USBCMD
);
uhci
->
is_suspended
=
0
;
case
UHCI_RESUMING_1
:
/* End global resume */
uhci
->
state
=
UHCI_RESUMING_2
;
outw
(
0
,
io_addr
+
USBCMD
);
/* Falls through */
/* Run and mark it configured with a 64-byte max packet */
case
UHCI_RESUMING_2
:
/* Wait for EOP to be sent */
outw
(
USBCMD_RS
|
USBCMD_CF
|
USBCMD_MAXP
,
io_addr
+
USBCMD
);
if
(
inw
(
io_addr
+
USBCMD
)
&
USBCMD_FGR
)
break
;
/* Run for at least 1 second, and
* mark it configured with a 64-byte max packet */
uhci
->
state
=
UHCI_RUNNING_GRACE
;
uhci
->
state_end
=
jiffies
+
HZ
;
outw
(
USBCMD_RS
|
USBCMD_CF
|
USBCMD_MAXP
,
io_addr
+
USBCMD
);
break
;
case
UHCI_RUNNING_GRACE
:
/* Now allowed to suspend */
uhci
->
state
=
UHCI_RUNNING
;
break
;
default:
break
;
}
}
}
static
int
ports_active
(
struct
uhci_hcd
*
uhci
)
static
int
ports_active
(
struct
uhci_hcd
*
uhci
)
...
@@ -1975,6 +1995,73 @@ static int ports_active(struct uhci_hcd *uhci)
...
@@ -1975,6 +1995,73 @@ static int ports_active(struct uhci_hcd *uhci)
return
connection
;
return
connection
;
}
}
static
int
suspend_allowed
(
struct
uhci_hcd
*
uhci
)
{
unsigned
int
io_addr
=
uhci
->
io_addr
;
int
i
;
if
(
!
uhci
->
hcd
.
pdev
||
uhci
->
hcd
.
pdev
->
vendor
!=
PCI_VENDOR_ID_INTEL
||
uhci
->
hcd
.
pdev
->
device
!=
PCI_DEVICE_ID_INTEL_82371AB_2
)
return
1
;
/* This is a 82371AB/EB/MB USB controller which has a bug that
* causes false resume indications if any port has an
* over current condition. To prevent problems, we will not
* allow a global suspend if any ports are OC.
*
* Some motherboards using the 82371AB/EB/MB (but not the USB portion)
* appear to hardwire the over current inputs active to disable
* the USB ports.
*/
/* check for over current condition on any port */
for
(
i
=
0
;
i
<
uhci
->
rh_numports
;
i
++
)
{
if
(
inw
(
io_addr
+
USBPORTSC1
+
i
*
2
)
&
USBPORTSC_OC
)
return
0
;
}
return
1
;
}
static
void
hc_state_transitions
(
struct
uhci_hcd
*
uhci
)
{
switch
(
uhci
->
state
)
{
case
UHCI_RUNNING
:
/* global suspend if nothing connected for 1 second */
if
(
!
ports_active
(
uhci
)
&&
suspend_allowed
(
uhci
))
{
uhci
->
state
=
UHCI_SUSPENDING_GRACE
;
uhci
->
state_end
=
jiffies
+
HZ
;
}
break
;
case
UHCI_SUSPENDING_GRACE
:
if
(
ports_active
(
uhci
))
uhci
->
state
=
UHCI_RUNNING
;
else
if
(
time_after_eq
(
jiffies
,
uhci
->
state_end
))
suspend_hc
(
uhci
);
break
;
case
UHCI_SUSPENDED
:
/* wakeup if requested by a device */
if
(
uhci
->
resume_detect
)
wakeup_hc
(
uhci
);
break
;
case
UHCI_RESUMING_1
:
case
UHCI_RESUMING_2
:
case
UHCI_RUNNING_GRACE
:
if
(
time_after_eq
(
jiffies
,
uhci
->
state_end
))
wakeup_hc
(
uhci
);
break
;
default:
break
;
}
}
static
void
start_hc
(
struct
uhci_hcd
*
uhci
)
static
void
start_hc
(
struct
uhci_hcd
*
uhci
)
{
{
unsigned
int
io_addr
=
uhci
->
io_addr
;
unsigned
int
io_addr
=
uhci
->
io_addr
;
...
@@ -2003,6 +2090,8 @@ static void start_hc(struct uhci_hcd *uhci)
...
@@ -2003,6 +2090,8 @@ static void start_hc(struct uhci_hcd *uhci)
outl
(
uhci
->
fl
->
dma_handle
,
io_addr
+
USBFLBASEADD
);
outl
(
uhci
->
fl
->
dma_handle
,
io_addr
+
USBFLBASEADD
);
/* Run and mark it configured with a 64-byte max packet */
/* Run and mark it configured with a 64-byte max packet */
uhci
->
state
=
UHCI_RUNNING_GRACE
;
uhci
->
state_end
=
jiffies
+
HZ
;
outw
(
USBCMD_RS
|
USBCMD_CF
|
USBCMD_MAXP
,
io_addr
+
USBCMD
);
outw
(
USBCMD_RS
|
USBCMD_CF
|
USBCMD_MAXP
,
io_addr
+
USBCMD
);
uhci
->
hcd
.
state
=
USB_STATE_READY
;
uhci
->
hcd
.
state
=
USB_STATE_READY
;
...
@@ -2101,8 +2190,6 @@ static int __devinit uhci_start(struct usb_hcd *hcd)
...
@@ -2101,8 +2190,6 @@ static int __devinit uhci_start(struct usb_hcd *hcd)
uhci
->
fsbr
=
0
;
uhci
->
fsbr
=
0
;
uhci
->
fsbrtimeout
=
0
;
uhci
->
fsbrtimeout
=
0
;
uhci
->
is_suspended
=
0
;
spin_lock_init
(
&
uhci
->
qh_remove_list_lock
);
spin_lock_init
(
&
uhci
->
qh_remove_list_lock
);
INIT_LIST_HEAD
(
&
uhci
->
qh_remove_list
);
INIT_LIST_HEAD
(
&
uhci
->
qh_remove_list
);
...
@@ -2335,7 +2422,11 @@ static int uhci_suspend(struct usb_hcd *hcd, u32 state)
...
@@ -2335,7 +2422,11 @@ static int uhci_suspend(struct usb_hcd *hcd, u32 state)
{
{
struct
uhci_hcd
*
uhci
=
hcd_to_uhci
(
hcd
);
struct
uhci_hcd
*
uhci
=
hcd_to_uhci
(
hcd
);
suspend_hc
(
uhci
);
/* Don't try to suspend broken motherboards, reset instead */
if
(
suspend_allowed
(
uhci
))
suspend_hc
(
uhci
);
else
reset_hc
(
uhci
);
return
0
;
return
0
;
}
}
...
@@ -2345,8 +2436,13 @@ static int uhci_resume(struct usb_hcd *hcd)
...
@@ -2345,8 +2436,13 @@ static int uhci_resume(struct usb_hcd *hcd)
pci_set_master
(
uhci
->
hcd
.
pdev
);
pci_set_master
(
uhci
->
hcd
.
pdev
);
reset_hc
(
uhci
);
if
(
uhci
->
state
==
UHCI_SUSPENDED
)
start_hc
(
uhci
);
uhci
->
resume_detect
=
1
;
else
{
reset_hc
(
uhci
);
start_hc
(
uhci
);
}
uhci
->
hcd
.
state
=
USB_STATE_READY
;
return
0
;
return
0
;
}
}
#endif
#endif
...
...
drivers/usb/host/uhci-hcd.h
View file @
1a569433
...
@@ -53,6 +53,7 @@
...
@@ -53,6 +53,7 @@
#define USBPORTSC_RD 0x0040
/* Resume Detect */
#define USBPORTSC_RD 0x0040
/* Resume Detect */
#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 */
#define USBPORTSC_OC 0x0400
/* Over Current condition */
#define USBPORTSC_SUSP 0x1000
/* Suspend */
#define USBPORTSC_SUSP 0x1000
/* Suspend */
/* Legacy support register */
/* Legacy support register */
...
@@ -282,6 +283,29 @@ static inline int __interval_to_skel(int interval)
...
@@ -282,6 +283,29 @@ static inline int __interval_to_skel(int interval)
return
0
;
/* int128 for 128-255 ms (Max.) */
return
0
;
/* int128 for 128-255 ms (Max.) */
}
}
/*
* Device states for the host controller.
*
* To prevent "bouncing" in the presence of electrical noise,
* we insist on a 1-second "grace" period, before switching to
* the RUNNING or SUSPENDED states, during which the state is
* not allowed to change.
*
* The resume process is divided into substates in order to avoid
* potentially length delays during the timer handler.
*
* States in which the host controller is halted must have values <= 0.
*/
enum
uhci_state
{
UHCI_RESET
,
UHCI_RUNNING_GRACE
,
/* Before RUNNING */
UHCI_RUNNING
,
/* The normal state */
UHCI_SUSPENDING_GRACE
,
/* Before SUSPENDED */
UHCI_SUSPENDED
=
-
10
,
/* When no devices are attached */
UHCI_RESUMING_1
,
UHCI_RESUMING_2
};
#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)
/*
/*
...
@@ -313,7 +337,10 @@ struct uhci_hcd {
...
@@ -313,7 +337,10 @@ struct uhci_hcd {
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 */
int
is_suspended
;
enum
uhci_state
state
;
/* FIXME: needs a spinlock */
unsigned
long
state_end
;
/* Time of next transition */
int
resume_detect
;
/* Need a Global Resume */
/* Main list of URB's currently controlled by this HC */
/* Main list of URB's currently controlled by this HC */
spinlock_t
urb_list_lock
;
spinlock_t
urb_list_lock
;
...
...
drivers/usb/misc/speedtch.c
View file @
1a569433
/******************************************************************************
/******************************************************************************
* speedtouch.c -
- Alcatel SpeedTouch USB xDSL modem driver.
* speedtouch.c -
Alcatel SpeedTouch USB xDSL modem driver
*
*
* Copyright (C) 2001, Alcatel
* Copyright (C) 2001, Alcatel
* Copyright (C) 2003, Duncan Sands
*
*
* This program is free software; you can redistribute it and/or modify it
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* under the terms of the GNU General Public License as published by the Free
...
@@ -40,7 +41,6 @@
...
@@ -40,7 +41,6 @@
* udsl_usb_send_data_context->urb to a pointer and adding code
* udsl_usb_send_data_context->urb to a pointer and adding code
* to alloc and free it
* to alloc and free it
* - remove_wait_queue() added to udsl_atm_processqueue_thread()
* - remove_wait_queue() added to udsl_atm_processqueue_thread()
* - Duncan Sands (duncan.sands@wanadoo.fr) is the new maintainer
*
*
* 1.5: - fixed memory leak when atmsar_decode_aal5 returned NULL.
* 1.5: - fixed memory leak when atmsar_decode_aal5 returned NULL.
* (reported by stephen.robinson@zen.co.uk)
* (reported by stephen.robinson@zen.co.uk)
...
@@ -97,48 +97,65 @@ static int udsl_print_packet (const unsigned char *data, int len);
...
@@ -97,48 +97,65 @@ static int udsl_print_packet (const unsigned char *data, int len);
#define DRIVER_DESC "Alcatel SpeedTouch USB driver"
#define DRIVER_DESC "Alcatel SpeedTouch USB driver"
#define DRIVER_VERSION "1.6"
#define DRIVER_VERSION "1.6"
static
const
char
udsl_driver_name
[]
=
"speedtch"
;
#define SPEEDTOUCH_VENDORID 0x06b9
#define SPEEDTOUCH_VENDORID 0x06b9
#define SPEEDTOUCH_PRODUCTID 0x4061
#define SPEEDTOUCH_PRODUCTID 0x4061
#define UDSL_NUMBER_RCV_URBS 1
#define UDSL_NUM_RCV_URBS 1
#define UDSL_NUMBER_SND_URBS 1
#define UDSL_NUM_SND_URBS 1
#define UDSL_NUMBER_SND_BUFS (2*UDSL_NUMBER_SND_URBS)
#define UDSL_NUM_RCV_BUFS (2*UDSL_NUM_RCV_URBS)
#define UDSL_RCV_BUFFER_SIZE (1*64)
/* ATM cells */
#define UDSL_NUM_SND_BUFS (2*UDSL_NUM_SND_URBS)
#define UDSL_SND_BUFFER_SIZE (1*64)
/* ATM cells */
#define UDSL_RCV_BUF_SIZE 32
/* ATM cells */
/* max should be (1500 IP mtu + 2 ppp bytes + 32 * 5 cellheader overhead) for
#define UDSL_SND_BUF_SIZE 64
/* ATM cells */
* PPPoA and (1500 + 14 + 32*5 cellheader overhead) for PPPoE */
#define UDSL_MAX_AAL5_MRU 2048
#define UDSL_IOCTL_START 1
#define UDSL_IOCTL_STOP 2
/* endpoint declarations */
#define UDSL_IOCTL_LINE_UP 1
#define UDSL_IOCTL_LINE_DOWN 2
#define UDSL_ENDPOINT_DATA_OUT 0x07
#define UDSL_ENDPOINT_DATA_OUT 0x07
#define UDSL_ENDPOINT_DATA_IN 0x87
#define UDSL_ENDPOINT_DATA_IN 0x87
#define ATM_CELL_HEADER (ATM_CELL_SIZE - ATM_CELL_PAYLOAD)
#define ATM_CELL_HEADER (ATM_CELL_SIZE - ATM_CELL_PAYLOAD)
#define UDSL_NUM_CELLS(x) (((x) + ATM_AAL5_TRAILER + ATM_CELL_PAYLOAD - 1) / ATM_CELL_PAYLOAD)
#define hex2int(c) ( (c >= '0')&&(c <= '9') ? (c - '0') : ((c & 0xf)+9) )
#define hex2int(c) ( (c >= '0') && (c <= '9') ? (c - '0') : ((c & 0xf) + 9) )
/* usb_device_id struct */
static
struct
usb_device_id
udsl_usb_ids
[]
=
{
static
struct
usb_device_id
udsl_usb_ids
[]
=
{
{
USB_DEVICE
(
SPEEDTOUCH_VENDORID
,
SPEEDTOUCH_PRODUCTID
)
},
{
USB_DEVICE
(
SPEEDTOUCH_VENDORID
,
SPEEDTOUCH_PRODUCTID
)
},
{
}
/* Terminating entry */
{
}
};
};
MODULE_DEVICE_TABLE
(
usb
,
udsl_usb_ids
);
MODULE_DEVICE_TABLE
(
usb
,
udsl_usb_ids
);
/* context declarations */
/* receive */
struct
udsl_receive_buffer
{
struct
list_head
list
;
unsigned
char
*
base
;
unsigned
int
filled_cells
;
};
struct
udsl_receiver
{
struct
udsl_receiver
{
struct
list_head
list
;
struct
list_head
list
;
struct
sk_buff
*
skb
;
struct
udsl_receive_buffer
*
buffer
;
struct
urb
*
urb
;
struct
urb
*
urb
;
struct
udsl_instance_data
*
instance
;
struct
udsl_instance_data
*
instance
;
};
};
struct
udsl_vcc_data
{
/* vpi/vci lookup */
struct
list_head
list
;
short
vpi
;
int
vci
;
struct
atm_vcc
*
vcc
;
/* raw cell reassembly */
struct
sk_buff
*
skb
;
unsigned
int
max_pdu
;
};
/* send */
struct
udsl_send_buffer
{
struct
udsl_send_buffer
{
struct
list_head
list
;
struct
list_head
list
;
unsigned
char
*
base
;
unsigned
char
*
base
;
...
@@ -157,73 +174,55 @@ struct udsl_control {
...
@@ -157,73 +174,55 @@ struct udsl_control {
struct
atm_skb_data
atm_data
;
struct
atm_skb_data
atm_data
;
unsigned
int
num_cells
;
unsigned
int
num_cells
;
unsigned
int
num_entire
;
unsigned
int
num_entire
;
unsigned
char
cell_header
[
ATM_CELL_HEADER
];
unsigned
int
pdu_padding
;
unsigned
int
pdu_padding
;
unsigned
char
cell_header
[
ATM_CELL_HEADER
];
unsigned
char
aal5_trailer
[
ATM_AAL5_TRAILER
];
unsigned
char
aal5_trailer
[
ATM_AAL5_TRAILER
];
};
};
#define UDSL_SKB(x) ((struct udsl_control *)(x)->cb)
#define UDSL_SKB(x) ((struct udsl_control *)(x)->cb)
struct
udsl_vcc_data
{
/* main driver data */
/* vpi/vci lookup */
struct
list_head
list
;
short
vpi
;
int
vci
;
struct
atm_vcc
*
vcc
;
/* raw cell reassembly */
unsigned
short
mtu
;
struct
sk_buff
*
reasBuffer
;
};
/*
* UDSL main driver data
*/
struct
udsl_instance_data
{
struct
udsl_instance_data
{
struct
semaphore
serialize
;
struct
semaphore
serialize
;
/*
usb
device part */
/*
USB
device part */
struct
usb_device
*
usb_dev
;
struct
usb_device
*
usb_dev
;
char
description
[
64
];
char
description
[
64
];
int
firmware_loaded
;
int
firmware_loaded
;
/*
atm
device part */
/*
ATM
device part */
struct
atm_dev
*
atm_dev
;
struct
atm_dev
*
atm_dev
;
struct
list_head
vcc_list
;
struct
list_head
vcc_list
;
/* receiving */
/* receive */
struct
udsl_receiver
all_receivers
[
UDSL_NUMBER_RCV_URBS
];
struct
udsl_receiver
receivers
[
UDSL_NUM_RCV_URBS
];
struct
udsl_receive_buffer
receive_buffers
[
UDSL_NUM_RCV_BUFS
];
spinlock_t
spare_receivers
_lock
;
spinlock_t
receive
_lock
;
struct
list_head
spare_receivers
;
struct
list_head
spare_receivers
;
struct
list_head
filled_receive_buffers
;
spinlock_t
completed_receivers_lock
;
struct
list_head
completed_receivers
;
struct
tasklet_struct
receive_tasklet
;
struct
tasklet_struct
receive_tasklet
;
struct
list_head
spare_receive_buffers
;
/* send
ing
*/
/* send */
struct
udsl_sender
all_senders
[
UDSL_NUMBER
_SND_URBS
];
struct
udsl_sender
senders
[
UDSL_NUM
_SND_URBS
];
struct
udsl_send_buffer
all_buffers
[
UDSL_NUMBER
_SND_BUFS
];
struct
udsl_send_buffer
send_buffers
[
UDSL_NUM
_SND_BUFS
];
struct
sk_buff_head
sndqueue
;
struct
sk_buff_head
sndqueue
;
spinlock_t
send_lock
;
spinlock_t
send_lock
;
struct
list_head
spare_senders
;
struct
list_head
spare_senders
;
struct
list_head
spare_buffers
;
struct
list_head
spare_
send_
buffers
;
struct
tasklet_struct
send_tasklet
;
struct
tasklet_struct
send_tasklet
;
struct
sk_buff
*
current_skb
;
/* being emptied */
struct
sk_buff
*
current_skb
;
/* being emptied */
struct
udsl_send_buffer
*
current_buffer
;
/* being filled */
struct
udsl_send_buffer
*
current_buffer
;
/* being filled */
struct
list_head
filled_buffers
;
struct
list_head
filled_
send_
buffers
;
};
};
static
const
char
udsl_driver_name
[]
=
"speedtch"
;
/* ATM */
/*
* atm driver prototypes and structures
*/
static
void
udsl_atm_dev_close
(
struct
atm_dev
*
dev
);
static
void
udsl_atm_dev_close
(
struct
atm_dev
*
dev
);
static
int
udsl_atm_open
(
struct
atm_vcc
*
vcc
,
short
vpi
,
int
vci
);
static
int
udsl_atm_open
(
struct
atm_vcc
*
vcc
,
short
vpi
,
int
vci
);
...
@@ -239,17 +238,17 @@ static struct atmdev_ops udsl_atm_devops = {
...
@@ -239,17 +238,17 @@ static struct atmdev_ops udsl_atm_devops = {
.
ioctl
=
udsl_atm_ioctl
,
.
ioctl
=
udsl_atm_ioctl
,
.
send
=
udsl_atm_send
,
.
send
=
udsl_atm_send
,
.
proc_read
=
udsl_atm_proc_read
,
.
proc_read
=
udsl_atm_proc_read
,
.
owner
=
THIS_MODULE
,
};
};
/*
/* USB */
* usb driver prototypes and structures
*/
static
int
udsl_usb_probe
(
struct
usb_interface
*
intf
,
const
struct
usb_device_id
*
id
);
static
int
udsl_usb_probe
(
struct
usb_interface
*
intf
,
const
struct
usb_device_id
*
id
);
static
void
udsl_usb_disconnect
(
struct
usb_interface
*
intf
);
static
void
udsl_usb_disconnect
(
struct
usb_interface
*
intf
);
static
int
udsl_usb_ioctl
(
struct
usb_interface
*
intf
,
unsigned
int
code
,
void
*
user_data
);
static
int
udsl_usb_ioctl
(
struct
usb_interface
*
intf
,
unsigned
int
code
,
void
*
user_data
);
static
struct
usb_driver
udsl_usb_driver
=
{
static
struct
usb_driver
udsl_usb_driver
=
{
.
owner
=
THIS_MODULE
,
.
name
=
udsl_driver_name
,
.
name
=
udsl_driver_name
,
.
probe
=
udsl_usb_probe
,
.
probe
=
udsl_usb_probe
,
.
disconnect
=
udsl_usb_disconnect
,
.
disconnect
=
udsl_usb_disconnect
,
...
@@ -272,133 +271,110 @@ static inline struct udsl_vcc_data *udsl_find_vcc (struct udsl_instance_data *in
...
@@ -272,133 +271,110 @@ static inline struct udsl_vcc_data *udsl_find_vcc (struct udsl_instance_data *in
return
NULL
;
return
NULL
;
}
}
static
struct
sk_buff
*
udsl_decode_rawcell
(
struct
udsl_instance_data
*
instance
,
struct
sk_buff
*
skb
,
struct
udsl_vcc_data
**
ctx
)
static
void
udsl_extract_cells
(
struct
udsl_instance_data
*
instance
,
unsigned
char
*
source
,
unsigned
int
howmany
)
{
{
if
(
!
instance
||
!
skb
||
!
ctx
)
struct
udsl_vcc_data
*
cached_vcc
=
NULL
;
return
NULL
;
struct
atm_vcc
*
vcc
;
if
(
!
skb
->
data
||
!
skb
->
tail
)
struct
sk_buff
*
skb
;
return
NULL
;
struct
udsl_vcc_data
*
vcc_data
;
int
cached_vci
=
0
;
unsigned
int
i
;
unsigned
int
length
;
unsigned
int
pdu_length
;
int
pti
;
int
vci
;
short
cached_vpi
=
0
;
short
vpi
;
while
(
skb
->
len
)
{
for
(
i
=
0
;
i
<
howmany
;
i
++
,
source
+=
ATM_CELL_SIZE
)
{
unsigned
char
*
cell
=
skb
->
data
;
vpi
=
((
source
[
0
]
&
0x0f
)
<<
4
)
|
(
source
[
1
]
>>
4
);
unsigned
char
*
cell_payload
;
vci
=
((
source
[
1
]
&
0x0f
)
<<
12
)
|
(
source
[
2
]
<<
4
)
|
(
source
[
3
]
>>
4
);
struct
udsl_vcc_data
*
vcc
;
pti
=
(
source
[
3
]
&
0x2
)
!=
0
;
short
vpi
;
int
vci
;
vpi
=
((
cell
[
0
]
&
0x0f
)
<<
4
)
|
(
cell
[
1
]
>>
4
);
vdbg
(
"udsl_extract_cells: vpi %hd, vci %d, pti %d"
,
vpi
,
vci
,
pti
);
vci
=
((
cell
[
1
]
&
0x0f
)
<<
12
)
|
(
cell
[
2
]
<<
4
)
|
(
cell
[
3
]
>>
4
);
vdbg
(
"udsl_decode_rawcell (0x%p, 0x%p, 0x%p) called"
,
instance
,
skb
,
ctx
);
if
(
cached_vcc
&&
(
vci
==
cached_vci
)
&&
(
vpi
==
cached_vpi
))
vdbg
(
"udsl_decode_rawcell skb->data %p, skb->tail %p"
,
skb
->
data
,
skb
->
tail
);
vcc_data
=
cached_vcc
;
else
if
((
vcc_data
=
udsl_find_vcc
(
instance
,
vpi
,
vci
)))
{
cached_vcc
=
vcc_data
;
cached_vpi
=
vpi
;
cached_vci
=
vci
;
}
else
{
dbg
(
"udsl_extract_cells: unknown vpi/vci (%hd/%d)!"
,
vpi
,
vci
);
continue
;
}
/* here should the header CRC check be... */
vcc
=
vcc_data
->
vcc
;
if
(
!
(
vcc
=
udsl_find_vcc
(
instance
,
vpi
,
vci
)))
{
if
(
!
vcc_data
->
skb
&&
!
(
vcc_data
->
skb
=
dev_alloc_skb
(
vcc_data
->
max_pdu
)))
{
dbg
(
"udsl_decode_rawcell: no vcc found for packet on vpi %d, vci %d"
,
vpi
,
vci
);
dbg
(
"udsl_extract_cells: no memory for skb (vcc: 0x%p)!"
,
vcc
);
__skb_pull
(
skb
,
min
(
skb
->
len
,
(
unsigned
)
53
));
if
(
pti
)
}
else
{
atomic_inc
(
&
vcc
->
stats
->
rx_err
);
vdbg
(
"udsl_decode_rawcell found vcc %p for packet on vpi %d, vci %d"
,
vcc
,
vpi
,
vci
);
continue
;
if
(
skb
->
len
>=
53
)
{
cell_payload
=
cell
+
5
;
if
(
!
vcc
->
reasBuffer
)
vcc
->
reasBuffer
=
dev_alloc_skb
(
vcc
->
mtu
);
/* if alloc fails, we just drop the cell. it is possible that we can still
* receive cells on other vcc's
*/
if
(
vcc
->
reasBuffer
)
{
/* if (buffer overrun) discard received cells until now */
if
((
vcc
->
reasBuffer
->
len
)
>
(
vcc
->
mtu
-
48
))
skb_trim
(
vcc
->
reasBuffer
,
0
);
/* copy data */
memcpy
(
vcc
->
reasBuffer
->
tail
,
cell_payload
,
48
);
skb_put
(
vcc
->
reasBuffer
,
48
);
/* check for end of buffer */
if
(
cell
[
3
]
&
0x2
)
{
struct
sk_buff
*
tmp
;
/* the aal5 buffer ends here, cut the buffer. */
/* buffer will always have at least one whole cell, so */
/* don't need to check return from skb_pull */
skb_pull
(
skb
,
53
);
*
ctx
=
vcc
;
tmp
=
vcc
->
reasBuffer
;
vcc
->
reasBuffer
=
NULL
;
vdbg
(
"udsl_decode_rawcell returns ATM_AAL5 pdu 0x%p with length %d"
,
tmp
,
tmp
->
len
);
return
tmp
;
}
}
/* flush the cell */
/* buffer will always contain at least one whole cell, so don't */
/* need to check return value from skb_pull */
skb_pull
(
skb
,
53
);
}
else
{
/* If data is corrupt and skb doesn't hold a whole cell, flush the lot */
__skb_pull
(
skb
,
skb
->
len
);
return
NULL
;
}
}
}
}
return
NULL
;
skb
=
vcc_data
->
skb
;
}
static
struct
sk_buff
*
udsl_decode_aal5
(
struct
udsl_vcc_data
*
ctx
,
struct
sk_buff
*
skb
)
if
(
skb
->
len
+
ATM_CELL_PAYLOAD
>
vcc_data
->
max_pdu
)
{
{
dbg
(
"udsl_extract_cells: buffer overrun (max_pdu: %u, skb->len %u, vcc: 0x%p)"
,
vcc_data
->
max_pdu
,
skb
->
len
,
vcc
);
uint
crc
=
0xffffffff
;
/* discard cells already received */
uint
length
,
pdu_crc
,
pdu_length
;
skb_trim
(
skb
,
0
);
BUG_ON
(
vcc_data
->
max_pdu
<
ATM_CELL_PAYLOAD
);
}
vdbg
(
"udsl_decode_aal5 (0x%p, 0x%p) called"
,
ctx
,
skb
);
memcpy
(
skb
->
tail
,
source
+
ATM_CELL_HEADER
,
ATM_CELL_PAYLOAD
);
__skb_put
(
skb
,
ATM_CELL_PAYLOAD
);
if
(
skb
->
len
&&
(
skb
->
len
%
48
))
if
(
pti
)
{
return
NULL
;
length
=
(
source
[
ATM_CELL_SIZE
-
6
]
<<
8
)
+
source
[
ATM_CELL_SIZE
-
5
]
;
length
=
(
skb
->
tail
[
-
6
]
<<
8
)
+
skb
->
tail
[
-
5
];
/* guard against overflow */
pdu_crc
=
if
(
length
>
ATM_MAX_AAL5_PDU
)
{
(
skb
->
tail
[
-
4
]
<<
24
)
+
(
skb
->
tail
[
-
3
]
<<
16
)
+
(
skb
->
tail
[
-
2
]
<<
8
)
+
skb
->
tail
[
-
1
];
dbg
(
"udsl_extract_cells: bogus length %u (vcc: 0x%p)"
,
length
,
vcc
);
pdu_length
=
((
length
+
47
+
8
)
/
48
)
*
48
;
goto
drop
;
}
vdbg
(
"udsl_decode_aal5: skb->len = %d, length = %d, pdu_crc = 0x%x, pdu_length = %d"
,
skb
->
len
,
length
,
pdu_crc
,
pdu_length
)
;
pdu_length
=
UDSL_NUM_CELLS
(
length
)
*
ATM_CELL_PAYLOAD
;
/* is skb long enough ? */
if
(
skb
->
len
<
pdu_length
)
{
if
(
skb
->
len
<
pdu_length
)
{
dbg
(
"udsl_extract_cells: bogus pdu_length %u (skb->len: %u, vcc: 0x%p)"
,
pdu_length
,
skb
->
len
,
vcc
);
atomic_inc
(
&
ctx
->
vcc
->
stats
->
rx_err
);
goto
drop
;
return
NULL
;
}
}
/* is skb too long ? */
if
(
crc32_be
(
~
0
,
skb
->
tail
-
pdu_length
,
pdu_length
)
!=
0xc704dd7b
)
{
if
(
skb
->
len
>
pdu_length
)
{
dbg
(
"udsl_extract_cells: packet failed crc check (vcc: 0x%p)"
,
vcc
);
dbg
(
"udsl_decode_aal5: Warning: readjusting illegal size %d -> %d"
,
skb
->
len
,
pdu_length
);
goto
drop
;
/* buffer is too long. we can try to recover
}
* if we discard the first part of the skb.
* the crc will decide whether this was ok
*/
skb_pull
(
skb
,
skb
->
len
-
pdu_length
);
}
crc
=
~
crc32_be
(
crc
,
skb
->
data
,
pdu_length
-
4
);
if
(
!
atm_charge
(
vcc
,
skb
->
truesize
))
{
dbg
(
"udsl_extract_cells: failed atm_charge (skb->truesize: %u)"
,
skb
->
truesize
);
goto
drop_no_stats
;
/* atm_charge increments rx_drop */
}
/* check crc */
/* now that we are sure to send the skb, it is ok to change skb->data */
if
(
pdu_crc
!=
crc
)
{
if
(
skb
->
len
>
pdu_length
)
dbg
(
"udsl_decode_aal5: crc check failed!"
);
skb_pull
(
skb
,
skb
->
len
-
pdu_length
);
/* discard initial junk */
atomic_inc
(
&
ctx
->
vcc
->
stats
->
rx_err
);
return
NULL
;
}
/* pdu is ok */
skb_trim
(
skb
,
length
);
/* drop zero padding and trailer */
skb_trim
(
skb
,
length
);
/* update stats */
atomic_inc
(
&
vcc
->
stats
->
rx
);
atomic_inc
(
&
ctx
->
vcc
->
stats
->
rx
);
vdbg
(
"udsl_decode_aal5 returns pdu 0x%p with length %d"
,
skb
,
skb
->
len
);
PACKETDEBUG
(
skb
->
data
,
skb
->
len
);
return
skb
;
vdbg
(
"udsl_extract_cells: sending skb 0x%p, skb->len %u, skb->truesize %u"
,
skb
,
skb
->
len
,
skb
->
truesize
);
vcc
->
push
(
vcc
,
skb
);
vcc_data
->
skb
=
NULL
;
continue
;
drop:
atomic_inc
(
&
vcc
->
stats
->
rx_err
);
drop_no_stats:
skb_trim
(
skb
,
0
);
}
}
}
}
...
@@ -406,7 +382,7 @@ static struct sk_buff *udsl_decode_aal5 (struct udsl_vcc_data *ctx, struct sk_bu
...
@@ -406,7 +382,7 @@ static struct sk_buff *udsl_decode_aal5 (struct udsl_vcc_data *ctx, struct sk_bu
** encode **
** encode **
*************/
*************/
static
const
unsigned
char
zeros
[
ATM_CELL_PAYLOAD
];
static
const
unsigned
char
zeros
[
ATM_CELL_PAYLOAD
];
static
void
udsl_groom_skb
(
struct
atm_vcc
*
vcc
,
struct
sk_buff
*
skb
)
static
void
udsl_groom_skb
(
struct
atm_vcc
*
vcc
,
struct
sk_buff
*
skb
)
{
{
...
@@ -421,7 +397,7 @@ static void udsl_groom_skb (struct atm_vcc *vcc, struct sk_buff *skb)
...
@@ -421,7 +397,7 @@ static void udsl_groom_skb (struct atm_vcc *vcc, struct sk_buff *skb)
ctrl
->
cell_header
[
3
]
=
vcc
->
vci
<<
4
;
ctrl
->
cell_header
[
3
]
=
vcc
->
vci
<<
4
;
ctrl
->
cell_header
[
4
]
=
0xec
;
ctrl
->
cell_header
[
4
]
=
0xec
;
ctrl
->
num_cells
=
(
skb
->
len
+
ATM_AAL5_TRAILER
+
ATM_CELL_PAYLOAD
-
1
)
/
ATM_CELL_PAYLOAD
;
ctrl
->
num_cells
=
UDSL_NUM_CELLS
(
skb
->
len
)
;
ctrl
->
num_entire
=
skb
->
len
/
ATM_CELL_PAYLOAD
;
ctrl
->
num_entire
=
skb
->
len
/
ATM_CELL_PAYLOAD
;
zero_padding
=
ctrl
->
num_cells
*
ATM_CELL_PAYLOAD
-
skb
->
len
-
ATM_AAL5_TRAILER
;
zero_padding
=
ctrl
->
num_cells
*
ATM_CELL_PAYLOAD
-
skb
->
len
-
ATM_AAL5_TRAILER
;
...
@@ -490,8 +466,7 @@ static unsigned int udsl_write_cells (unsigned int howmany, struct sk_buff *skb,
...
@@ -490,8 +466,7 @@ static unsigned int udsl_write_cells (unsigned int howmany, struct sk_buff *skb,
memset
(
target
,
0
,
ATM_CELL_PAYLOAD
-
ATM_AAL5_TRAILER
);
memset
(
target
,
0
,
ATM_CELL_PAYLOAD
-
ATM_AAL5_TRAILER
);
target
+=
ATM_CELL_PAYLOAD
-
ATM_AAL5_TRAILER
;
target
+=
ATM_CELL_PAYLOAD
-
ATM_AAL5_TRAILER
;
if
(
--
ctrl
->
num_cells
)
BUG_ON
(
--
ctrl
->
num_cells
);
BUG
();
}
}
memcpy
(
target
,
ctrl
->
aal5_trailer
,
ATM_AAL5_TRAILER
);
memcpy
(
target
,
ctrl
->
aal5_trailer
,
ATM_AAL5_TRAILER
);
...
@@ -511,145 +486,89 @@ static unsigned int udsl_write_cells (unsigned int howmany, struct sk_buff *skb,
...
@@ -511,145 +486,89 @@ static unsigned int udsl_write_cells (unsigned int howmany, struct sk_buff *skb,
static
void
udsl_complete_receive
(
struct
urb
*
urb
,
struct
pt_regs
*
regs
)
static
void
udsl_complete_receive
(
struct
urb
*
urb
,
struct
pt_regs
*
regs
)
{
{
struct
udsl_receive_buffer
*
buf
;
struct
udsl_instance_data
*
instance
;
struct
udsl_instance_data
*
instance
;
struct
udsl_receiver
*
rcv
;
struct
udsl_receiver
*
rcv
;
unsigned
long
flags
;
unsigned
long
flags
;
if
(
!
urb
||
!
(
rcv
=
urb
->
context
)
||
!
(
instance
=
rcv
->
instance
)
)
{
if
(
!
urb
||
!
(
rcv
=
urb
->
context
))
{
dbg
(
"udsl_complete_receive: bad urb!"
);
dbg
(
"udsl_complete_receive: bad urb!"
);
return
;
return
;
}
}
vdbg
(
"udsl_complete_receive entered (urb 0x%p, status %d)"
,
urb
,
urb
->
status
);
instance
=
rcv
->
instance
;
buf
=
rcv
->
buffer
;
buf
->
filled_cells
=
urb
->
actual_length
/
ATM_CELL_SIZE
;
vdbg
(
"udsl_complete_receive: urb 0x%p, status %d, actual_length %d, filled_cells %u, rcv 0x%p, buf 0x%p"
,
urb
,
urb
->
status
,
urb
->
actual_length
,
buf
->
filled_cells
,
rcv
,
buf
);
BUG_ON
(
buf
->
filled_cells
>
UDSL_RCV_BUF_SIZE
);
/* may not be in_interrupt() */
/* may not be in_interrupt() */
spin_lock_irqsave
(
&
instance
->
completed_receivers_lock
,
flags
);
spin_lock_irqsave
(
&
instance
->
receive_lock
,
flags
);
list_add_tail
(
&
rcv
->
list
,
&
instance
->
completed_receivers
);
list_add
(
&
rcv
->
list
,
&
instance
->
spare_receivers
);
tasklet_schedule
(
&
instance
->
receive_tasklet
);
list_add_tail
(
&
buf
->
list
,
&
instance
->
filled_receive_buffers
);
spin_unlock_irqrestore
(
&
instance
->
completed_receivers_lock
,
flags
);
if
(
likely
(
!
urb
->
status
))
tasklet_schedule
(
&
instance
->
receive_tasklet
);
spin_unlock_irqrestore
(
&
instance
->
receive_lock
,
flags
);
}
}
static
void
udsl_process_receive
(
unsigned
long
data
)
static
void
udsl_process_receive
(
unsigned
long
data
)
{
{
struct
udsl_receive_buffer
*
buf
;
struct
udsl_instance_data
*
instance
=
(
struct
udsl_instance_data
*
)
data
;
struct
udsl_instance_data
*
instance
=
(
struct
udsl_instance_data
*
)
data
;
struct
udsl_receiver
*
rcv
;
struct
udsl_receiver
*
rcv
;
unsigned
char
*
data_start
;
struct
sk_buff
*
skb
;
struct
urb
*
urb
;
struct
udsl_vcc_data
*
atmsar_vcc
=
NULL
;
struct
sk_buff
*
new
=
NULL
,
*
tmp
=
NULL
;
int
err
;
int
err
;
vdbg
(
"udsl_process_receive entered"
);
made_progress:
while
(
!
list_empty
(
&
instance
->
spare_receive_buffers
))
{
spin_lock_irq
(
&
instance
->
completed_receivers_lock
);
spin_lock_irq
(
&
instance
->
receive_lock
);
while
(
!
list_empty
(
&
instance
->
completed_receivers
))
{
if
(
list_empty
(
&
instance
->
spare_receivers
))
{
rcv
=
list_entry
(
instance
->
completed_receivers
.
next
,
struct
udsl_receiver
,
list
);
spin_unlock_irq
(
&
instance
->
receive_lock
);
list_del
(
&
rcv
->
list
);
spin_unlock_irq
(
&
instance
->
completed_receivers_lock
);
urb
=
rcv
->
urb
;
vdbg
(
"udsl_process_receive: got packet %p with length %d and status %d"
,
urb
,
urb
->
actual_length
,
urb
->
status
);
switch
(
urb
->
status
)
{
case
0
:
vdbg
(
"udsl_process_receive: processing urb with rcv %p, urb %p, skb %p"
,
rcv
,
urb
,
rcv
->
skb
);
/* update the skb structure */
skb
=
rcv
->
skb
;
skb_trim
(
skb
,
0
);
skb_put
(
skb
,
urb
->
actual_length
);
data_start
=
skb
->
data
;
vdbg
(
"skb->len = %d"
,
skb
->
len
);
PACKETDEBUG
(
skb
->
data
,
skb
->
len
);
while
((
new
=
udsl_decode_rawcell
(
instance
,
skb
,
&
atmsar_vcc
)))
{
vdbg
(
"(after cell processing)skb->len = %d"
,
new
->
len
);
tmp
=
new
;
new
=
udsl_decode_aal5
(
atmsar_vcc
,
new
);
/* we can't send NULL skbs upstream, the ATM layer would try to close the vcc... */
if
(
new
)
{
vdbg
(
"(after aal5 decap) skb->len = %d"
,
new
->
len
);
if
(
new
->
len
&&
atm_charge
(
atmsar_vcc
->
vcc
,
new
->
truesize
))
{
PACKETDEBUG
(
new
->
data
,
new
->
len
);
atmsar_vcc
->
vcc
->
push
(
atmsar_vcc
->
vcc
,
new
);
}
else
{
dbg
(
"dropping incoming packet : vcc->sk->rcvbuf = %d, skb->true_size = %d"
,
atmsar_vcc
->
vcc
->
sk
->
rcvbuf
,
new
->
truesize
);
dev_kfree_skb
(
new
);
}
}
else
{
dbg
(
"udsl_decode_aal5 returned NULL!"
);
dev_kfree_skb
(
tmp
);
}
}
/* restore skb */
skb_push
(
skb
,
skb
->
data
-
data_start
);
usb_fill_bulk_urb
(
urb
,
instance
->
usb_dev
,
usb_rcvbulkpipe
(
instance
->
usb_dev
,
UDSL_ENDPOINT_DATA_IN
),
(
unsigned
char
*
)
rcv
->
skb
->
data
,
UDSL_RCV_BUFFER_SIZE
*
ATM_CELL_SIZE
,
udsl_complete_receive
,
rcv
);
if
(
!
(
err
=
usb_submit_urb
(
urb
,
GFP_ATOMIC
)))
break
;
dbg
(
"udsl_process_receive: submission failed (%d)"
,
err
);
/* fall through */
default:
/* error or urb unlinked */
vdbg
(
"udsl_process_receive: adding to spare_receivers"
);
spin_lock_irq
(
&
instance
->
spare_receivers_lock
);
list_add
(
&
rcv
->
list
,
&
instance
->
spare_receivers
);
spin_unlock_irq
(
&
instance
->
spare_receivers_lock
);
break
;
break
;
}
/* switch */
}
rcv
=
list_entry
(
instance
->
spare_receivers
.
next
,
struct
udsl_receiver
,
list
);
spin_lock_irq
(
&
instance
->
completed_receivers_lock
);
list_del
(
&
rcv
->
list
);
}
/* while */
spin_unlock_irq
(
&
instance
->
receive_lock
);
spin_unlock_irq
(
&
instance
->
completed_receivers_lock
);
vdbg
(
"udsl_process_receive successful"
);
}
static
void
udsl_fire_receivers
(
struct
udsl_instance_data
*
instance
)
{
struct
list_head
receivers
,
*
pos
,
*
n
;
INIT_LIST_HEAD
(
&
receivers
);
down
(
&
instance
->
serialize
);
spin_lock_irq
(
&
instance
->
spare_receivers_lock
);
list_splice_init
(
&
instance
->
spare_receivers
,
&
receivers
);
spin_unlock_irq
(
&
instance
->
spare_receivers_lock
);
list_for_each_safe
(
pos
,
n
,
&
receivers
)
{
buf
=
list_entry
(
instance
->
spare_receive_buffers
.
next
,
struct
udsl_receive_buffer
,
list
);
struct
udsl_receiver
*
rcv
=
list_entry
(
pos
,
struct
udsl_receiver
,
list
);
list_del
(
&
buf
->
list
);
dbg
(
"udsl_fire_receivers: firing urb %p"
,
rcv
->
urb
)
;
rcv
->
buffer
=
buf
;
usb_fill_bulk_urb
(
rcv
->
urb
,
usb_fill_bulk_urb
(
rcv
->
urb
,
instance
->
usb_dev
,
instance
->
usb_dev
,
usb_rcvbulkpipe
(
instance
->
usb_dev
,
UDSL_ENDPOINT_DATA_IN
),
usb_rcvbulkpipe
(
instance
->
usb_dev
,
UDSL_ENDPOINT_DATA_IN
),
(
unsigned
char
*
)
rcv
->
skb
->
data
,
buf
->
base
,
UDSL_RCV_BUF
FER
_SIZE
*
ATM_CELL_SIZE
,
UDSL_RCV_BUF_SIZE
*
ATM_CELL_SIZE
,
udsl_complete_receive
,
udsl_complete_receive
,
rcv
);
rcv
);
if
(
usb_submit_urb
(
rcv
->
urb
,
GFP_KERNEL
)
<
0
)
{
vdbg
(
"udsl_process_receive: sending urb 0x%p, rcv 0x%p, buf 0x%p"
,
rcv
->
urb
,
rcv
,
buf
);
dbg
(
"udsl_fire_receivers: submit failed!"
);
spin_lock_irq
(
&
instance
->
spare_receivers_lock
);
if
((
err
=
usb_submit_urb
(
rcv
->
urb
,
GFP_ATOMIC
))
<
0
)
{
list_move
(
pos
,
&
instance
->
spare_receivers
);
dbg
(
"udsl_process_receive: urb submission failed (%d)!"
,
err
);
spin_unlock_irq
(
&
instance
->
spare_receivers_lock
);
list_add
(
&
buf
->
list
,
&
instance
->
spare_receive_buffers
);
spin_lock_irq
(
&
instance
->
receive_lock
);
list_add
(
&
rcv
->
list
,
&
instance
->
spare_receivers
);
spin_unlock_irq
(
&
instance
->
receive_lock
);
break
;
}
}
}
}
up
(
&
instance
->
serialize
);
spin_lock_irq
(
&
instance
->
receive_lock
);
if
(
list_empty
(
&
instance
->
filled_receive_buffers
))
{
spin_unlock_irq
(
&
instance
->
receive_lock
);
return
;
/* done - no more buffers */
}
buf
=
list_entry
(
instance
->
filled_receive_buffers
.
next
,
struct
udsl_receive_buffer
,
list
);
list_del
(
&
buf
->
list
);
spin_unlock_irq
(
&
instance
->
receive_lock
);
vdbg
(
"udsl_process_receive: processing buf 0x%p"
,
buf
);
udsl_extract_cells
(
instance
,
buf
->
base
,
buf
->
filled_cells
);
list_add
(
&
buf
->
list
,
&
instance
->
spare_receive_buffers
);
goto
made_progress
;
}
}
...
@@ -673,7 +592,7 @@ static void udsl_complete_send (struct urb *urb, struct pt_regs *regs)
...
@@ -673,7 +592,7 @@ static void udsl_complete_send (struct urb *urb, struct pt_regs *regs)
/* may not be in_interrupt() */
/* may not be in_interrupt() */
spin_lock_irqsave
(
&
instance
->
send_lock
,
flags
);
spin_lock_irqsave
(
&
instance
->
send_lock
,
flags
);
list_add
(
&
snd
->
list
,
&
instance
->
spare_senders
);
list_add
(
&
snd
->
list
,
&
instance
->
spare_senders
);
list_add
(
&
snd
->
buffer
->
list
,
&
instance
->
spare_buffers
);
list_add
(
&
snd
->
buffer
->
list
,
&
instance
->
spare_
send_
buffers
);
tasklet_schedule
(
&
instance
->
send_tasklet
);
tasklet_schedule
(
&
instance
->
send_tasklet
);
spin_unlock_irqrestore
(
&
instance
->
send_lock
,
flags
);
spin_unlock_irqrestore
(
&
instance
->
send_lock
,
flags
);
}
}
...
@@ -681,17 +600,17 @@ static void udsl_complete_send (struct urb *urb, struct pt_regs *regs)
...
@@ -681,17 +600,17 @@ static void udsl_complete_send (struct urb *urb, struct pt_regs *regs)
static
void
udsl_process_send
(
unsigned
long
data
)
static
void
udsl_process_send
(
unsigned
long
data
)
{
{
struct
udsl_send_buffer
*
buf
;
struct
udsl_send_buffer
*
buf
;
int
err
;
struct
udsl_instance_data
*
instance
=
(
struct
udsl_instance_data
*
)
data
;
struct
udsl_instance_data
*
instance
=
(
struct
udsl_instance_data
*
)
data
;
unsigned
int
num_written
;
struct
sk_buff
*
skb
;
struct
sk_buff
*
skb
;
struct
udsl_sender
*
snd
;
struct
udsl_sender
*
snd
;
int
err
;
unsigned
int
num_written
;
made_progress:
made_progress:
spin_lock_irq
(
&
instance
->
send_lock
);
spin_lock_irq
(
&
instance
->
send_lock
);
while
(
!
list_empty
(
&
instance
->
spare_senders
))
{
while
(
!
list_empty
(
&
instance
->
spare_senders
))
{
if
(
!
list_empty
(
&
instance
->
filled_buffers
))
{
if
(
!
list_empty
(
&
instance
->
filled_
send_
buffers
))
{
buf
=
list_entry
(
instance
->
filled_buffers
.
next
,
struct
udsl_send_buffer
,
list
);
buf
=
list_entry
(
instance
->
filled_
send_
buffers
.
next
,
struct
udsl_send_buffer
,
list
);
list_del
(
&
buf
->
list
);
list_del
(
&
buf
->
list
);
}
else
if
((
buf
=
instance
->
current_buffer
))
{
}
else
if
((
buf
=
instance
->
current_buffer
))
{
instance
->
current_buffer
=
NULL
;
instance
->
current_buffer
=
NULL
;
...
@@ -707,7 +626,7 @@ static void udsl_process_send (unsigned long data)
...
@@ -707,7 +626,7 @@ static void udsl_process_send (unsigned long data)
instance
->
usb_dev
,
instance
->
usb_dev
,
usb_sndbulkpipe
(
instance
->
usb_dev
,
UDSL_ENDPOINT_DATA_OUT
),
usb_sndbulkpipe
(
instance
->
usb_dev
,
UDSL_ENDPOINT_DATA_OUT
),
buf
->
base
,
buf
->
base
,
(
UDSL_SND_BUF
FER
_SIZE
-
buf
->
free_cells
)
*
ATM_CELL_SIZE
,
(
UDSL_SND_BUF_SIZE
-
buf
->
free_cells
)
*
ATM_CELL_SIZE
,
udsl_complete_send
,
udsl_complete_send
,
snd
);
snd
);
...
@@ -718,33 +637,32 @@ static void udsl_process_send (unsigned long data)
...
@@ -718,33 +637,32 @@ static void udsl_process_send (unsigned long data)
spin_lock_irq
(
&
instance
->
send_lock
);
spin_lock_irq
(
&
instance
->
send_lock
);
list_add
(
&
snd
->
list
,
&
instance
->
spare_senders
);
list_add
(
&
snd
->
list
,
&
instance
->
spare_senders
);
spin_unlock_irq
(
&
instance
->
send_lock
);
spin_unlock_irq
(
&
instance
->
send_lock
);
list_add
(
&
buf
->
list
,
&
instance
->
filled_buffers
);
list_add
(
&
buf
->
list
,
&
instance
->
filled_
send_
buffers
);
return
;
return
;
/* bail out */
}
}
spin_lock_irq
(
&
instance
->
send_lock
);
spin_lock_irq
(
&
instance
->
send_lock
);
}
/* while */
}
/* while */
spin_unlock_irq
(
&
instance
->
send_lock
);
spin_unlock_irq
(
&
instance
->
send_lock
);
if
(
!
instance
->
current_skb
&&
!
(
instance
->
current_skb
=
skb_dequeue
(
&
instance
->
sndqueue
)))
{
if
(
!
instance
->
current_skb
&&
!
(
instance
->
current_skb
=
skb_dequeue
(
&
instance
->
sndqueue
)))
return
;
/* done - no more skbs */
return
;
/* done - no more skbs */
}
skb
=
instance
->
current_skb
;
skb
=
instance
->
current_skb
;
if
(
!
(
buf
=
instance
->
current_buffer
))
{
if
(
!
(
buf
=
instance
->
current_buffer
))
{
spin_lock_irq
(
&
instance
->
send_lock
);
spin_lock_irq
(
&
instance
->
send_lock
);
if
(
list_empty
(
&
instance
->
spare_buffers
))
{
if
(
list_empty
(
&
instance
->
spare_
send_
buffers
))
{
instance
->
current_buffer
=
NULL
;
instance
->
current_buffer
=
NULL
;
spin_unlock_irq
(
&
instance
->
send_lock
);
spin_unlock_irq
(
&
instance
->
send_lock
);
return
;
/* done - no more buffers */
return
;
/* done - no more buffers */
}
}
buf
=
list_entry
(
instance
->
spare_buffers
.
next
,
struct
udsl_send_buffer
,
list
);
buf
=
list_entry
(
instance
->
spare_
send_
buffers
.
next
,
struct
udsl_send_buffer
,
list
);
list_del
(
&
buf
->
list
);
list_del
(
&
buf
->
list
);
spin_unlock_irq
(
&
instance
->
send_lock
);
spin_unlock_irq
(
&
instance
->
send_lock
);
buf
->
free_start
=
buf
->
base
;
buf
->
free_start
=
buf
->
base
;
buf
->
free_cells
=
UDSL_SND_BUF
FER
_SIZE
;
buf
->
free_cells
=
UDSL_SND_BUF_SIZE
;
instance
->
current_buffer
=
buf
;
instance
->
current_buffer
=
buf
;
}
}
...
@@ -754,7 +672,7 @@ static void udsl_process_send (unsigned long data)
...
@@ -754,7 +672,7 @@ static void udsl_process_send (unsigned long data)
vdbg
(
"udsl_process_send: wrote %u cells from skb 0x%p to buffer 0x%p"
,
num_written
,
skb
,
buf
);
vdbg
(
"udsl_process_send: wrote %u cells from skb 0x%p to buffer 0x%p"
,
num_written
,
skb
,
buf
);
if
(
!
(
buf
->
free_cells
-=
num_written
))
{
if
(
!
(
buf
->
free_cells
-=
num_written
))
{
list_add_tail
(
&
buf
->
list
,
&
instance
->
filled_buffers
);
list_add_tail
(
&
buf
->
list
,
&
instance
->
filled_
send_
buffers
);
instance
->
current_buffer
=
NULL
;
instance
->
current_buffer
=
NULL
;
}
}
...
@@ -766,7 +684,7 @@ static void udsl_process_send (unsigned long data)
...
@@ -766,7 +684,7 @@ static void udsl_process_send (unsigned long data)
if
(
vcc
->
pop
)
if
(
vcc
->
pop
)
vcc
->
pop
(
vcc
,
skb
);
vcc
->
pop
(
vcc
,
skb
);
else
else
kfree_skb
(
skb
);
dev_
kfree_skb
(
skb
);
instance
->
current_skb
=
NULL
;
instance
->
current_skb
=
NULL
;
atomic_inc
(
&
vcc
->
stats
->
tx
);
atomic_inc
(
&
vcc
->
stats
->
tx
);
...
@@ -788,7 +706,7 @@ static void udsl_cancel_send (struct udsl_instance_data *instance, struct atm_vc
...
@@ -788,7 +706,7 @@ static void udsl_cancel_send (struct udsl_instance_data *instance, struct atm_vc
if
(
vcc
->
pop
)
if
(
vcc
->
pop
)
vcc
->
pop
(
vcc
,
skb
);
vcc
->
pop
(
vcc
,
skb
);
else
else
kfree_skb
(
skb
);
dev_
kfree_skb
(
skb
);
}
}
spin_unlock_irq
(
&
instance
->
sndqueue
.
lock
);
spin_unlock_irq
(
&
instance
->
sndqueue
.
lock
);
...
@@ -799,7 +717,7 @@ static void udsl_cancel_send (struct udsl_instance_data *instance, struct atm_vc
...
@@ -799,7 +717,7 @@ static void udsl_cancel_send (struct udsl_instance_data *instance, struct atm_vc
if
(
vcc
->
pop
)
if
(
vcc
->
pop
)
vcc
->
pop
(
vcc
,
skb
);
vcc
->
pop
(
vcc
,
skb
);
else
else
kfree_skb
(
skb
);
dev_
kfree_skb
(
skb
);
}
}
tasklet_enable
(
&
instance
->
send_tasklet
);
tasklet_enable
(
&
instance
->
send_tasklet
);
dbg
(
"udsl_cancel_send done"
);
dbg
(
"udsl_cancel_send done"
);
...
@@ -851,6 +769,7 @@ static void udsl_atm_dev_close (struct atm_dev *dev)
...
@@ -851,6 +769,7 @@ static void udsl_atm_dev_close (struct atm_dev *dev)
dbg
(
"udsl_atm_dev_close: queue has %u elements"
,
instance
->
sndqueue
.
qlen
);
dbg
(
"udsl_atm_dev_close: queue has %u elements"
,
instance
->
sndqueue
.
qlen
);
tasklet_kill
(
&
instance
->
receive_tasklet
);
tasklet_kill
(
&
instance
->
send_tasklet
);
tasklet_kill
(
&
instance
->
send_tasklet
);
kfree
(
instance
);
kfree
(
instance
);
dev
->
dev_data
=
NULL
;
dev
->
dev_data
=
NULL
;
...
@@ -871,8 +790,8 @@ static int udsl_atm_proc_read (struct atm_dev *atm_dev, loff_t *pos, char *page)
...
@@ -871,8 +790,8 @@ static int udsl_atm_proc_read (struct atm_dev *atm_dev, loff_t *pos, char *page)
if
(
!
left
--
)
if
(
!
left
--
)
return
sprintf
(
page
,
"MAC: %02x:%02x:%02x:%02x:%02x:%02x
\n
"
,
return
sprintf
(
page
,
"MAC: %02x:%02x:%02x:%02x:%02x:%02x
\n
"
,
atm_dev
->
esi
[
0
],
atm_dev
->
esi
[
1
],
atm_dev
->
esi
[
2
],
atm_dev
->
esi
[
0
],
atm_dev
->
esi
[
1
],
atm_dev
->
esi
[
2
],
atm_dev
->
esi
[
3
],
atm_dev
->
esi
[
4
],
atm_dev
->
esi
[
5
]);
atm_dev
->
esi
[
3
],
atm_dev
->
esi
[
4
],
atm_dev
->
esi
[
5
]);
if
(
!
left
--
)
if
(
!
left
--
)
return
sprintf
(
page
,
"AAL5: tx %d ( %d err ), rx %d ( %d err, %d drop )
\n
"
,
return
sprintf
(
page
,
"AAL5: tx %d ( %d err ), rx %d ( %d err, %d drop )
\n
"
,
...
@@ -925,7 +844,7 @@ static int udsl_atm_open (struct atm_vcc *vcc, short vpi, int vci)
...
@@ -925,7 +844,7 @@ static int udsl_atm_open (struct atm_vcc *vcc, short vpi, int vci)
return
-
EINVAL
;
return
-
EINVAL
;
/* only support AAL5 */
/* only support AAL5 */
if
(
vcc
->
qos
.
aal
!=
ATM_AAL5
)
if
(
(
vcc
->
qos
.
aal
!=
ATM_AAL5
)
||
(
vcc
->
qos
.
rxtp
.
max_sdu
<
0
)
||
(
vcc
->
qos
.
rxtp
.
max_sdu
>
ATM_MAX_AAL5_PDU
)
)
return
-
EINVAL
;
return
-
EINVAL
;
if
(
!
instance
->
firmware_loaded
)
{
if
(
!
instance
->
firmware_loaded
)
{
...
@@ -949,7 +868,7 @@ static int udsl_atm_open (struct atm_vcc *vcc, short vpi, int vci)
...
@@ -949,7 +868,7 @@ static int udsl_atm_open (struct atm_vcc *vcc, short vpi, int vci)
new
->
vcc
=
vcc
;
new
->
vcc
=
vcc
;
new
->
vpi
=
vpi
;
new
->
vpi
=
vpi
;
new
->
vci
=
vci
;
new
->
vci
=
vci
;
new
->
m
tu
=
UDSL_MAX_AAL5_MRU
;
new
->
m
ax_pdu
=
max
(
1
,
UDSL_NUM_CELLS
(
vcc
->
qos
.
rxtp
.
max_sdu
))
*
ATM_CELL_PAYLOAD
;
vcc
->
dev_data
=
new
;
vcc
->
dev_data
=
new
;
vcc
->
vpi
=
vpi
;
vcc
->
vpi
=
vpi
;
...
@@ -965,7 +884,7 @@ static int udsl_atm_open (struct atm_vcc *vcc, short vpi, int vci)
...
@@ -965,7 +884,7 @@ static int udsl_atm_open (struct atm_vcc *vcc, short vpi, int vci)
up
(
&
instance
->
serialize
);
up
(
&
instance
->
serialize
);
udsl_fire_receivers
(
instance
);
tasklet_schedule
(
&
instance
->
receive_tasklet
);
dbg
(
"udsl_atm_open: allocated vcc data 0x%p (max_pdu: %u)"
,
new
,
new
->
max_pdu
);
dbg
(
"udsl_atm_open: allocated vcc data 0x%p (max_pdu: %u)"
,
new
,
new
->
max_pdu
);
...
@@ -994,9 +913,9 @@ static void udsl_atm_close (struct atm_vcc *vcc)
...
@@ -994,9 +913,9 @@ static void udsl_atm_close (struct atm_vcc *vcc)
list_del
(
&
vcc_data
->
list
);
list_del
(
&
vcc_data
->
list
);
tasklet_enable
(
&
instance
->
receive_tasklet
);
tasklet_enable
(
&
instance
->
receive_tasklet
);
if
(
vcc_data
->
reasBuffer
)
if
(
vcc_data
->
skb
)
kfree_skb
(
vcc_data
->
reasBuffer
);
dev_kfree_skb
(
vcc_data
->
skb
);
vcc_data
->
reasBuffer
=
NULL
;
vcc_data
->
skb
=
NULL
;
kfree
(
vcc_data
);
kfree
(
vcc_data
);
vcc
->
dev_data
=
NULL
;
vcc
->
dev_data
=
NULL
;
...
@@ -1041,7 +960,9 @@ static int udsl_set_alternate (struct udsl_instance_data *instance)
...
@@ -1041,7 +960,9 @@ static int udsl_set_alternate (struct udsl_instance_data *instance)
instance
->
firmware_loaded
=
1
;
instance
->
firmware_loaded
=
1
;
}
}
up
(
&
instance
->
serialize
);
up
(
&
instance
->
serialize
);
udsl_fire_receivers
(
instance
);
tasklet_schedule
(
&
instance
->
receive_tasklet
);
return
0
;
return
0
;
}
}
...
@@ -1057,10 +978,10 @@ static int udsl_usb_ioctl (struct usb_interface *intf, unsigned int code, void *
...
@@ -1057,10 +978,10 @@ static int udsl_usb_ioctl (struct usb_interface *intf, unsigned int code, void *
}
}
switch
(
code
)
{
switch
(
code
)
{
case
UDSL_IOCTL_
START
:
case
UDSL_IOCTL_
LINE_UP
:
instance
->
atm_dev
->
signal
=
ATM_PHY_SIG_FOUND
;
instance
->
atm_dev
->
signal
=
ATM_PHY_SIG_FOUND
;
return
udsl_set_alternate
(
instance
);
return
udsl_set_alternate
(
instance
);
case
UDSL_IOCTL_
STOP
:
case
UDSL_IOCTL_
LINE_DOWN
:
instance
->
atm_dev
->
signal
=
ATM_PHY_SIG_LOST
;
instance
->
atm_dev
->
signal
=
ATM_PHY_SIG_LOST
;
return
0
;
return
0
;
default:
default:
...
@@ -1101,31 +1022,25 @@ static int udsl_usb_probe (struct usb_interface *intf, const struct usb_device_i
...
@@ -1101,31 +1022,25 @@ static int udsl_usb_probe (struct usb_interface *intf, const struct usb_device_i
INIT_LIST_HEAD
(
&
instance
->
vcc_list
);
INIT_LIST_HEAD
(
&
instance
->
vcc_list
);
spin_lock_init
(
&
instance
->
spare_receivers
_lock
);
spin_lock_init
(
&
instance
->
receive
_lock
);
INIT_LIST_HEAD
(
&
instance
->
spare_receivers
);
INIT_LIST_HEAD
(
&
instance
->
spare_receivers
);
INIT_LIST_HEAD
(
&
instance
->
filled_receive_buffers
);
spin_lock_init
(
&
instance
->
completed_receivers_lock
);
INIT_LIST_HEAD
(
&
instance
->
completed_receivers
);
tasklet_init
(
&
instance
->
receive_tasklet
,
udsl_process_receive
,
(
unsigned
long
)
instance
);
tasklet_init
(
&
instance
->
receive_tasklet
,
udsl_process_receive
,
(
unsigned
long
)
instance
);
INIT_LIST_HEAD
(
&
instance
->
spare_receive_buffers
);
skb_queue_head_init
(
&
instance
->
sndqueue
);
skb_queue_head_init
(
&
instance
->
sndqueue
);
spin_lock_init
(
&
instance
->
send_lock
);
spin_lock_init
(
&
instance
->
send_lock
);
INIT_LIST_HEAD
(
&
instance
->
spare_senders
);
INIT_LIST_HEAD
(
&
instance
->
spare_senders
);
INIT_LIST_HEAD
(
&
instance
->
spare_buffers
);
INIT_LIST_HEAD
(
&
instance
->
spare_
send_
buffers
);
tasklet_init
(
&
instance
->
send_tasklet
,
udsl_process_send
,
(
unsigned
long
)
instance
);
tasklet_init
(
&
instance
->
send_tasklet
,
udsl_process_send
,
(
unsigned
long
)
instance
);
INIT_LIST_HEAD
(
&
instance
->
filled_buffers
);
INIT_LIST_HEAD
(
&
instance
->
filled_
send_
buffers
);
/* receive init */
/* receive init */
for
(
i
=
0
;
i
<
UDSL_NUMBER_RCV_URBS
;
i
++
)
{
for
(
i
=
0
;
i
<
UDSL_NUM_RCV_URBS
;
i
++
)
{
struct
udsl_receiver
*
rcv
=
&
(
instance
->
all_receivers
[
i
]);
struct
udsl_receiver
*
rcv
=
&
(
instance
->
receivers
[
i
]);
if
(
!
(
rcv
->
skb
=
dev_alloc_skb
(
UDSL_RCV_BUFFER_SIZE
*
ATM_CELL_SIZE
)))
{
dbg
(
"udsl_usb_probe: no memory for skb %d!"
,
i
);
goto
fail
;
}
if
(
!
(
rcv
->
urb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
)))
{
if
(
!
(
rcv
->
urb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
)))
{
dbg
(
"udsl_usb_probe: no memory for receive urb %d!"
,
i
);
dbg
(
"udsl_usb_probe: no memory for receive urb %d!"
,
i
);
...
@@ -1135,13 +1050,22 @@ static int udsl_usb_probe (struct usb_interface *intf, const struct usb_device_i
...
@@ -1135,13 +1050,22 @@ static int udsl_usb_probe (struct usb_interface *intf, const struct usb_device_i
rcv
->
instance
=
instance
;
rcv
->
instance
=
instance
;
list_add
(
&
rcv
->
list
,
&
instance
->
spare_receivers
);
list_add
(
&
rcv
->
list
,
&
instance
->
spare_receivers
);
}
for
(
i
=
0
;
i
<
UDSL_NUM_RCV_BUFS
;
i
++
)
{
struct
udsl_receive_buffer
*
buf
=
&
(
instance
->
receive_buffers
[
i
]);
if
(
!
(
buf
->
base
=
kmalloc
(
UDSL_RCV_BUF_SIZE
*
ATM_CELL_SIZE
,
GFP_KERNEL
)))
{
dbg
(
"udsl_usb_probe: no memory for receive buffer %d!"
,
i
);
goto
fail
;
}
dbg
(
"udsl_usb_probe: skb->truesize = %d (asked for %d)"
,
rcv
->
skb
->
truesize
,
UDSL_RCV_BUF_SIZE
*
ATM_CELL_SIZE
);
list_add
(
&
buf
->
list
,
&
instance
->
spare_receive_buffers
);
}
}
/* send init */
/* send init */
for
(
i
=
0
;
i
<
UDSL_NUM
BER
_SND_URBS
;
i
++
)
{
for
(
i
=
0
;
i
<
UDSL_NUM_SND_URBS
;
i
++
)
{
struct
udsl_sender
*
snd
=
&
(
instance
->
all_senders
[
i
]);
struct
udsl_sender
*
snd
=
&
(
instance
->
senders
[
i
]);
if
(
!
(
snd
->
urb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
)))
{
if
(
!
(
snd
->
urb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
)))
{
dbg
(
"udsl_usb_probe: no memory for send urb %d!"
,
i
);
dbg
(
"udsl_usb_probe: no memory for send urb %d!"
,
i
);
...
@@ -1153,18 +1077,18 @@ static int udsl_usb_probe (struct usb_interface *intf, const struct usb_device_i
...
@@ -1153,18 +1077,18 @@ static int udsl_usb_probe (struct usb_interface *intf, const struct usb_device_i
list_add
(
&
snd
->
list
,
&
instance
->
spare_senders
);
list_add
(
&
snd
->
list
,
&
instance
->
spare_senders
);
}
}
for
(
i
=
0
;
i
<
UDSL_NUM
BER
_SND_BUFS
;
i
++
)
{
for
(
i
=
0
;
i
<
UDSL_NUM_SND_BUFS
;
i
++
)
{
struct
udsl_send_buffer
*
buf
=
&
(
instance
->
all_buffers
[
i
]);
struct
udsl_send_buffer
*
buf
=
&
(
instance
->
send_buffers
[
i
]);
if
(
!
(
buf
->
base
=
kmalloc
(
UDSL_SND_BUF
FER
_SIZE
*
ATM_CELL_SIZE
,
GFP_KERNEL
)))
{
if
(
!
(
buf
->
base
=
kmalloc
(
UDSL_SND_BUF_SIZE
*
ATM_CELL_SIZE
,
GFP_KERNEL
)))
{
dbg
(
"udsl_usb_probe: no memory for send buffer %d!"
,
i
);
dbg
(
"udsl_usb_probe: no memory for send buffer %d!"
,
i
);
goto
fail
;
goto
fail
;
}
}
list_add
(
&
buf
->
list
,
&
instance
->
spare_buffers
);
list_add
(
&
buf
->
list
,
&
instance
->
spare_
send_
buffers
);
}
}
/*
atm
init */
/*
ATM
init */
if
(
!
(
instance
->
atm_dev
=
atm_dev_register
(
udsl_driver_name
,
&
udsl_atm_devops
,
-
1
,
0
)))
{
if
(
!
(
instance
->
atm_dev
=
atm_dev_register
(
udsl_driver_name
,
&
udsl_atm_devops
,
-
1
,
0
)))
{
dbg
(
"udsl_usb_probe: failed to register ATM device!"
);
dbg
(
"udsl_usb_probe: failed to register ATM device!"
);
goto
fail
;
goto
fail
;
...
@@ -1174,14 +1098,14 @@ static int udsl_usb_probe (struct usb_interface *intf, const struct usb_device_i
...
@@ -1174,14 +1098,14 @@ static int udsl_usb_probe (struct usb_interface *intf, const struct usb_device_i
instance
->
atm_dev
->
ci_range
.
vci_bits
=
ATM_CI_MAX
;
instance
->
atm_dev
->
ci_range
.
vci_bits
=
ATM_CI_MAX
;
instance
->
atm_dev
->
signal
=
ATM_PHY_SIG_UNKNOWN
;
instance
->
atm_dev
->
signal
=
ATM_PHY_SIG_UNKNOWN
;
/* t
mp init atm
device, set to 128kbit */
/* t
emp init ATM
device, set to 128kbit */
instance
->
atm_dev
->
link_rate
=
128
*
1000
/
424
;
instance
->
atm_dev
->
link_rate
=
128
*
1000
/
424
;
/* set MAC address, it is stored in the serial number */
/* set MAC address, it is stored in the serial number */
memset
(
instance
->
atm_dev
->
esi
,
0
,
sizeof
(
instance
->
atm_dev
->
esi
));
memset
(
instance
->
atm_dev
->
esi
,
0
,
sizeof
(
instance
->
atm_dev
->
esi
));
if
(
usb_string
(
dev
,
dev
->
descriptor
.
iSerialNumber
,
mac_str
,
sizeof
(
mac_str
))
==
12
)
if
(
usb_string
(
dev
,
dev
->
descriptor
.
iSerialNumber
,
mac_str
,
sizeof
(
mac_str
))
==
12
)
for
(
i
=
0
;
i
<
6
;
i
++
)
for
(
i
=
0
;
i
<
6
;
i
++
)
instance
->
atm_dev
->
esi
[
i
]
=
(
hex2int
(
mac_str
[
i
*
2
])
*
16
)
+
(
hex2int
(
mac_str
[
i
*
2
+
1
]));
instance
->
atm_dev
->
esi
[
i
]
=
(
hex2int
(
mac_str
[
i
*
2
])
*
16
)
+
(
hex2int
(
mac_str
[
i
*
2
+
1
]));
/* device description */
/* device description */
buf
=
instance
->
description
;
buf
=
instance
->
description
;
...
@@ -1215,20 +1139,17 @@ static int udsl_usb_probe (struct usb_interface *intf, const struct usb_device_i
...
@@ -1215,20 +1139,17 @@ static int udsl_usb_probe (struct usb_interface *intf, const struct usb_device_i
return
0
;
return
0
;
fail:
fail:
for
(
i
=
0
;
i
<
UDSL_NUM
BER
_SND_BUFS
;
i
++
)
for
(
i
=
0
;
i
<
UDSL_NUM_SND_BUFS
;
i
++
)
kfree
(
instance
->
all_buffers
[
i
].
base
);
kfree
(
instance
->
send_buffers
[
i
].
base
);
for
(
i
=
0
;
i
<
UDSL_NUM
BER
_SND_URBS
;
i
++
)
for
(
i
=
0
;
i
<
UDSL_NUM_SND_URBS
;
i
++
)
usb_free_urb
(
instance
->
all_senders
[
i
].
urb
);
usb_free_urb
(
instance
->
senders
[
i
].
urb
);
for
(
i
=
0
;
i
<
UDSL_NUM
BER_RCV_URBS
;
i
++
)
{
for
(
i
=
0
;
i
<
UDSL_NUM
_RCV_BUFS
;
i
++
)
struct
udsl_receiver
*
rcv
=
&
(
instance
->
all_receivers
[
i
]
);
kfree
(
instance
->
receive_buffers
[
i
].
base
);
usb_free_urb
(
rcv
->
urb
);
for
(
i
=
0
;
i
<
UDSL_NUM_RCV_URBS
;
i
++
)
usb_free_urb
(
instance
->
receivers
[
i
].
urb
);
if
(
rcv
->
skb
)
kfree_skb
(
rcv
->
skb
);
}
kfree
(
instance
);
kfree
(
instance
);
...
@@ -1239,7 +1160,7 @@ static void udsl_usb_disconnect (struct usb_interface *intf)
...
@@ -1239,7 +1160,7 @@ static void udsl_usb_disconnect (struct usb_interface *intf)
{
{
struct
udsl_instance_data
*
instance
=
usb_get_intfdata
(
intf
);
struct
udsl_instance_data
*
instance
=
usb_get_intfdata
(
intf
);
struct
list_head
*
pos
;
struct
list_head
*
pos
;
unsigned
int
count
=
0
;
unsigned
int
count
;
int
result
,
i
;
int
result
,
i
;
dbg
(
"udsl_usb_disconnect entered"
);
dbg
(
"udsl_usb_disconnect entered"
);
...
@@ -1251,38 +1172,25 @@ static void udsl_usb_disconnect (struct usb_interface *intf)
...
@@ -1251,38 +1172,25 @@ static void udsl_usb_disconnect (struct usb_interface *intf)
return
;
return
;
}
}
tasklet_disable
(
&
instance
->
receive_tasklet
);
/* receive finalize */
/* receive finalize */
down
(
&
instance
->
serialize
);
/* vs udsl_fire_receivers */
tasklet_disable
(
&
instance
->
receive_tasklet
);
/* no need to take the spinlock */
list_for_each
(
pos
,
&
instance
->
spare_receivers
)
if
(
++
count
>
UDSL_NUMBER_RCV_URBS
)
panic
(
__FILE__
": memory corruption detected at line %d!
\n
"
,
__LINE__
);
INIT_LIST_HEAD
(
&
instance
->
spare_receivers
);
up
(
&
instance
->
serialize
);
dbg
(
"udsl_usb_disconnect: flushed %u spare receivers"
,
count
);
count
=
UDSL_NUMBER_RCV_URBS
-
count
;
for
(
i
=
0
;
i
<
UDSL_NUM
BER
_RCV_URBS
;
i
++
)
for
(
i
=
0
;
i
<
UDSL_NUM_RCV_URBS
;
i
++
)
if
((
result
=
usb_unlink_urb
(
instance
->
all_receivers
[
i
].
urb
))
<
0
)
if
((
result
=
usb_unlink_urb
(
instance
->
receivers
[
i
].
urb
))
<
0
)
dbg
(
"udsl_usb_disconnect: usb_unlink_urb on receive urb %d returned %d"
,
i
,
result
);
dbg
(
"udsl_usb_disconnect: usb_unlink_urb on receive urb %d returned %d"
,
i
,
result
);
/* wait for completion handlers to finish */
/* wait for completion handlers to finish */
do
{
do
{
unsigned
int
completed
=
0
;
count
=
0
;
spin_lock_irq
(
&
instance
->
receive_lock
);
spin_lock_irq
(
&
instance
->
completed_receivers_lock
);
list_for_each
(
pos
,
&
instance
->
spare_receivers
)
list_for_each
(
pos
,
&
instance
->
completed_receivers
)
if
(
++
count
>
UDSL_NUM_RCV_URBS
)
if
(
++
completed
>
count
)
panic
(
__FILE__
": memory corruption detected at line %d!
\n
"
,
__LINE__
);
panic
(
__FILE__
": memory corruption detected at line %d!
\n
"
,
__LINE__
);
spin_unlock_irq
(
&
instance
->
completed_receivers
_lock
);
spin_unlock_irq
(
&
instance
->
receive
_lock
);
dbg
(
"udsl_usb_disconnect: found %u
completed receivers"
,
completed
);
dbg
(
"udsl_usb_disconnect: found %u
spare receivers"
,
count
);
if
(
co
mpleted
==
count
)
if
(
co
unt
==
UDSL_NUM_RCV_URBS
)
break
;
break
;
set_current_state
(
TASK_RUNNING
);
set_current_state
(
TASK_RUNNING
);
...
@@ -1290,37 +1198,36 @@ static void udsl_usb_disconnect (struct usb_interface *intf)
...
@@ -1290,37 +1198,36 @@ static void udsl_usb_disconnect (struct usb_interface *intf)
}
while
(
1
);
}
while
(
1
);
/* no need to take the spinlock */
/* no need to take the spinlock */
INIT_LIST_HEAD
(
&
instance
->
completed_receivers
);
INIT_LIST_HEAD
(
&
instance
->
filled_receive_buffers
);
INIT_LIST_HEAD
(
&
instance
->
spare_receive_buffers
);
tasklet_enable
(
&
instance
->
receive_tasklet
);
tasklet_enable
(
&
instance
->
receive_tasklet
);
tasklet_kill
(
&
instance
->
receive_tasklet
);
for
(
i
=
0
;
i
<
UDSL_NUM
BER_RCV_URBS
;
i
++
)
{
for
(
i
=
0
;
i
<
UDSL_NUM
_RCV_URBS
;
i
++
)
struct
udsl_receiver
*
rcv
=
&
(
instance
->
all_receivers
[
i
]
);
usb_free_urb
(
instance
->
receivers
[
i
].
urb
);
usb_free_urb
(
rcv
->
urb
);
for
(
i
=
0
;
i
<
UDSL_NUM_RCV_BUFS
;
i
++
)
kfree_skb
(
rcv
->
skb
);
kfree
(
instance
->
receive_buffers
[
i
].
base
);
}
/* send finalize */
/* send finalize */
tasklet_disable
(
&
instance
->
send_tasklet
);
tasklet_disable
(
&
instance
->
send_tasklet
);
for
(
i
=
0
;
i
<
UDSL_NUM
BER
_SND_URBS
;
i
++
)
for
(
i
=
0
;
i
<
UDSL_NUM_SND_URBS
;
i
++
)
if
((
result
=
usb_unlink_urb
(
instance
->
all_senders
[
i
].
urb
))
<
0
)
if
((
result
=
usb_unlink_urb
(
instance
->
senders
[
i
].
urb
))
<
0
)
dbg
(
"udsl_usb_disconnect: usb_unlink_urb on send urb %d returned %d"
,
i
,
result
);
dbg
(
"udsl_usb_disconnect: usb_unlink_urb on send urb %d returned %d"
,
i
,
result
);
/* wait for completion handlers to finish */
/* wait for completion handlers to finish */
do
{
do
{
count
=
0
;
count
=
0
;
spin_lock
(
&
instance
->
send_lock
);
spin_lock
_irq
(
&
instance
->
send_lock
);
list_for_each
(
pos
,
&
instance
->
spare_senders
)
list_for_each
(
pos
,
&
instance
->
spare_senders
)
if
(
++
count
>
UDSL_NUM
BER
_SND_URBS
)
if
(
++
count
>
UDSL_NUM_SND_URBS
)
panic
(
__FILE__
": memory corruption detected at line %d!
\n
"
,
__LINE__
);
panic
(
__FILE__
": memory corruption detected at line %d!
\n
"
,
__LINE__
);
spin_unlock
(
&
instance
->
send_lock
);
spin_unlock
_irq
(
&
instance
->
send_lock
);
dbg
(
"udsl_usb_disconnect: found %u spare senders"
,
count
);
dbg
(
"udsl_usb_disconnect: found %u spare senders"
,
count
);
if
(
count
==
UDSL_NUM
BER
_SND_URBS
)
if
(
count
==
UDSL_NUM_SND_URBS
)
break
;
break
;
set_current_state
(
TASK_RUNNING
);
set_current_state
(
TASK_RUNNING
);
...
@@ -1329,22 +1236,22 @@ static void udsl_usb_disconnect (struct usb_interface *intf)
...
@@ -1329,22 +1236,22 @@ static void udsl_usb_disconnect (struct usb_interface *intf)
/* no need to take the spinlock */
/* no need to take the spinlock */
INIT_LIST_HEAD
(
&
instance
->
spare_senders
);
INIT_LIST_HEAD
(
&
instance
->
spare_senders
);
INIT_LIST_HEAD
(
&
instance
->
spare_buffers
);
INIT_LIST_HEAD
(
&
instance
->
spare_
send_
buffers
);
instance
->
current_buffer
=
NULL
;
instance
->
current_buffer
=
NULL
;
tasklet_enable
(
&
instance
->
send_tasklet
);
tasklet_enable
(
&
instance
->
send_tasklet
);
for
(
i
=
0
;
i
<
UDSL_NUM
BER
_SND_URBS
;
i
++
)
for
(
i
=
0
;
i
<
UDSL_NUM_SND_URBS
;
i
++
)
usb_free_urb
(
instance
->
all_senders
[
i
].
urb
);
usb_free_urb
(
instance
->
senders
[
i
].
urb
);
for
(
i
=
0
;
i
<
UDSL_NUM
BER
_SND_BUFS
;
i
++
)
for
(
i
=
0
;
i
<
UDSL_NUM_SND_BUFS
;
i
++
)
kfree
(
instance
->
all_buffers
[
i
].
base
);
kfree
(
instance
->
send_buffers
[
i
].
base
);
wmb
();
wmb
();
instance
->
usb_dev
=
NULL
;
instance
->
usb_dev
=
NULL
;
/*
atm
finalize */
/*
ATM
finalize */
shutdown_atm_dev
(
instance
->
atm_dev
);
/* frees instance */
shutdown_atm_dev
(
instance
->
atm_dev
);
/* frees instance
, kills tasklets
*/
}
}
...
@@ -1392,10 +1299,10 @@ static int udsl_print_packet (const unsigned char *data, int len)
...
@@ -1392,10 +1299,10 @@ static int udsl_print_packet (const unsigned char *data, int len)
int
i
=
0
,
j
=
0
;
int
i
=
0
,
j
=
0
;
for
(
i
=
0
;
i
<
len
;)
{
for
(
i
=
0
;
i
<
len
;)
{
buffer
[
0
]
=
'\0'
;
buffer
[
0
]
=
'\0'
;
sprintf
(
buffer
,
"%.3d :"
,
i
);
sprintf
(
buffer
,
"%.3d :"
,
i
);
for
(
j
=
0
;
(
j
<
16
)
&&
(
i
<
len
);
j
++
,
i
++
)
{
for
(
j
=
0
;
(
j
<
16
)
&&
(
i
<
len
);
j
++
,
i
++
)
{
sprintf
(
buffer
,
"%s %2.2x"
,
buffer
,
data
[
i
]);
sprintf
(
buffer
,
"%s %2.2x"
,
buffer
,
data
[
i
]);
}
}
dbg
(
"%s"
,
buffer
);
dbg
(
"%s"
,
buffer
);
}
}
...
...
drivers/usb/storage/transport.c
View file @
1a569433
...
@@ -988,7 +988,7 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
...
@@ -988,7 +988,7 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
US_DEBUGP
(
"Bulk status Sig 0x%x T 0x%x R %d Stat 0x%x
\n
"
,
US_DEBUGP
(
"Bulk status Sig 0x%x T 0x%x R %d Stat 0x%x
\n
"
,
le32_to_cpu
(
bcs
.
Signature
),
bcs
.
Tag
,
le32_to_cpu
(
bcs
.
Signature
),
bcs
.
Tag
,
bcs
.
Residue
,
bcs
.
Status
);
bcs
.
Residue
,
bcs
.
Status
);
if
(
bcs
.
Signature
!=
cpu_to_le32
(
US_BULK_CS_SIGN
)
||
if
(
(
bcs
.
Signature
!=
cpu_to_le32
(
US_BULK_CS_SIGN
)
&&
bcs
.
Signature
!=
cpu_to_le32
(
US_BULK_CS_OLYMPUS_SIGN
)
)
||
bcs
.
Tag
!=
bcb
.
Tag
||
bcs
.
Tag
!=
bcb
.
Tag
||
bcs
.
Status
>
US_BULK_STAT_PHASE
)
{
bcs
.
Status
>
US_BULK_STAT_PHASE
)
{
US_DEBUGP
(
"Bulk logical error
\n
"
);
US_DEBUGP
(
"Bulk logical error
\n
"
);
...
...
drivers/usb/storage/transport.h
View file @
1a569433
...
@@ -105,6 +105,8 @@ struct bulk_cs_wrap {
...
@@ -105,6 +105,8 @@ struct bulk_cs_wrap {
#define US_BULK_CS_WRAP_LEN 13
#define US_BULK_CS_WRAP_LEN 13
#define US_BULK_CS_SIGN 0x53425355
/* spells out 'USBS' */
#define US_BULK_CS_SIGN 0x53425355
/* spells out 'USBS' */
/* This is for Olympus Camedia digital cameras */
#define US_BULK_CS_OLYMPUS_SIGN 0x55425355
/* spells out 'USBU' */
#define US_BULK_STAT_OK 0
#define US_BULK_STAT_OK 0
#define US_BULK_STAT_FAIL 1
#define US_BULK_STAT_FAIL 1
#define US_BULK_STAT_PHASE 2
#define US_BULK_STAT_PHASE 2
...
...
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