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
9cfc20f1
Commit
9cfc20f1
authored
Jul 04, 2002
by
Greg Kroah-Hartman
Browse files
Options
Browse Files
Download
Plain Diff
Merge kroah.com:/home/linux/linux/BK/bleeding-2.5
into kroah.com:/home/linux/linux/BK/gregkh-2.5
parents
8263f8c5
9dbfec80
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
368 additions
and
523 deletions
+368
-523
drivers/usb/host/Config.help
drivers/usb/host/Config.help
+2
-41
drivers/usb/host/Config.in
drivers/usb/host/Config.in
+3
-17
drivers/usb/host/ohci-dbg.c
drivers/usb/host/ohci-dbg.c
+2
-0
drivers/usb/host/ohci-hcd.c
drivers/usb/host/ohci-hcd.c
+10
-2
drivers/usb/host/uhci-hcd.c
drivers/usb/host/uhci-hcd.c
+8
-30
drivers/usb/host/usb-uhci-hcd.c
drivers/usb/host/usb-uhci-hcd.c
+6
-12
drivers/usb/host/usb-uhci-q.c
drivers/usb/host/usb-uhci-q.c
+1
-57
drivers/usb/net/pegasus.c
drivers/usb/net/pegasus.c
+162
-117
drivers/usb/net/pegasus.h
drivers/usb/net/pegasus.h
+5
-12
drivers/usb/net/rtl8150.c
drivers/usb/net/rtl8150.c
+21
-28
drivers/usb/storage/transport.c
drivers/usb/storage/transport.c
+27
-74
drivers/usb/storage/usb.c
drivers/usb/storage/usb.c
+120
-133
drivers/usb/storage/usb.h
drivers/usb/storage/usb.h
+1
-0
No files found.
drivers/usb/host/Config.help
View file @
9cfc20f1
...
@@ -36,26 +36,7 @@ CONFIG_USB_OHCI_HCD
...
@@ -36,26 +36,7 @@ CONFIG_USB_OHCI_HCD
The module will be called ohci-hcd.o. If you want to compile it
The module will be called ohci-hcd.o. If you want to compile it
as a module, say M here and read <file:Documentation/modules.txt>.
as a module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_UHCI
CONFIG_USB_UHCI_HCD_ALT
The Universal Host Controller Interface is a standard by Intel for
accessing the USB hardware in the PC (which is also called the USB
host controller). If your USB host controller conforms to this
standard, you may want to say Y, but see below. All recent boards
with Intel PCI chipsets (like intel 430TX, 440FX, 440LX, 440BX,
i810, i820) conform to this standard. Also all VIA PCI chipsets
(like VIA VP2, VP3, MVP3, Apollo Pro, Apollo Pro II or Apollo Pro
133).
Currently there exist two drivers for UHCI host controllers: this
one and the so-called JE driver, which you can get from
"UHCI alternate (JE) support", below. You need only one.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called usb-uhci.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_UHCI_ALT
The Universal Host Controller Interface is a standard by Intel for
The Universal Host Controller Interface is a standard by Intel for
accessing the USB hardware in the PC (which is also called the USB
accessing the USB hardware in the PC (which is also called the USB
host controller). If your USB host controller conforms to this
host controller). If your USB host controller conforms to this
...
@@ -65,31 +46,11 @@ CONFIG_USB_UHCI_ALT
...
@@ -65,31 +46,11 @@ CONFIG_USB_UHCI_ALT
(like VIA VP2, VP3, MVP3, Apollo Pro, Apollo Pro II or Apollo Pro
(like VIA VP2, VP3, MVP3, Apollo Pro, Apollo Pro II or Apollo Pro
133). If unsure, say Y.
133). If unsure, say Y.
Currently there exist two drivers for UHCI host controllers: this
so-called JE driver, and the one you get from "UHCI support", above.
You need only one.
This code is also available as a module ( = code which can be
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
inserted in and removed from the running kernel whenever you want).
The module will be called uhci.o. If you want to compile it as a
The module will be called uhci
-hcd
.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_OHCI
The Open Host Controller Interface is a standard by
Compaq/Microsoft/National for accessing the USB PC hardware (also
called USB host controller). If your USB host controller conforms to
this standard, say Y. The USB host controllers on most non-Intel
architectures and on several x86 compatibles with non-Intel chipsets
-- like SiS (aktual 610, 610 and so on) or ALi (ALi IV, ALi V,
Aladdin Pro..) -- conform to this standard.
You may want to read <file:Documentation/usb/ohci.txt>.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called usb-ohci.o. If you want to compile it
as a module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_SL811HS
CONFIG_USB_SL811HS
Say Y here if you have a SL811HS USB host controller in your system.
Say Y here if you have a SL811HS USB host controller in your system.
...
...
drivers/usb/host/Config.in
View file @
9cfc20f1
...
@@ -2,23 +2,9 @@
...
@@ -2,23 +2,9 @@
# USB Host Controller Drivers
# USB Host Controller Drivers
#
#
comment 'USB Host Controller Drivers'
comment 'USB Host Controller Drivers'
dep_tristate ' EHCI HCD (USB 2.0) support (EXPERIMENTAL)' CONFIG_USB_EHCI_HCD $CONFIG_USB $CONFIG_EXPERIMENTAL
dep_tristate ' EHCI HCD (USB 2.0) support' CONFIG_USB_EHCI_HCD $CONFIG_USB
dep_tristate ' OHCI HCD support (EXPERIMENTAL)' CONFIG_USB_OHCI_HCD $CONFIG_USB $CONFIG_EXPERIMENTAL
dep_tristate ' OHCI HCD support' CONFIG_USB_OHCI_HCD $CONFIG_USB
if [ "$CONFIG_USB_UHCI_HCD_ALT" != "y" ]; then
dep_tristate ' UHCI HCD (most Intel and VIA) support' CONFIG_USB_UHCI_HCD_ALT $CONFIG_USB
dep_tristate ' UHCI HCD (most Intel and VIA) support (EXPERIMENTAL)' CONFIG_USB_UHCI_HCD $CONFIG_USB $CONFIG_EXPERIMENTAL
fi
if [ "$CONFIG_USB_UHCI_HCD" != "y" ]; then
dep_tristate ' UHCI HCD Alternate (most Intel and VIA) support (EXPERIMENTAL)' CONFIG_USB_UHCI_HCD_ALT $CONFIG_USB $CONFIG_EXPERIMENTAL
fi
#if [ "$CONFIG_USB_UHCI_ALT" != "y" ]; then
# dep_tristate ' UHCI (Intel PIIX4, VIA, ...) support' CONFIG_USB_UHCI $CONFIG_USB
#fi
#if [ "$CONFIG_USB_UHCI" != "y" ]; then
# dep_tristate ' UHCI Alternate Driver (JE) support' CONFIG_USB_UHCI_ALT $CONFIG_USB
#else
# define_bool CONFIG_USB_UHCI_ALT n
#fi
#dep_tristate ' OHCI (Compaq, iMacs, OPTi, SiS, ALi, ...) support' CONFIG_USB_OHCI $CONFIG_USB
if [ "$CONFIG_ARM" = "y" ]; then
if [ "$CONFIG_ARM" = "y" ]; then
dep_tristate ' SA1111 OHCI-compatible host interface support' CONFIG_USB_OHCI_SA1111 $CONFIG_USB
dep_tristate ' SA1111 OHCI-compatible host interface support' CONFIG_USB_OHCI_SA1111 $CONFIG_USB
dep_tristate ' SL811HS support' CONFIG_USB_SL811HS $CONFIG_USB
dep_tristate ' SL811HS support' CONFIG_USB_SL811HS $CONFIG_USB
...
...
drivers/usb/host/ohci-dbg.c
View file @
9cfc20f1
...
@@ -190,6 +190,8 @@ static void ohci_dump_roothub (struct ohci_hcd *controller, int verbose)
...
@@ -190,6 +190,8 @@ static void ohci_dump_roothub (struct ohci_hcd *controller, int verbose)
__u32
temp
,
ndp
,
i
;
__u32
temp
,
ndp
,
i
;
temp
=
roothub_a
(
controller
);
temp
=
roothub_a
(
controller
);
if
(
temp
==
~
(
u32
)
0
)
return
;
ndp
=
(
temp
&
RH_A_NDP
);
ndp
=
(
temp
&
RH_A_NDP
);
if
(
verbose
)
{
if
(
verbose
)
{
...
...
drivers/usb/host/ohci-hcd.c
View file @
9cfc20f1
...
@@ -502,11 +502,19 @@ static void ohci_irq (struct usb_hcd *hcd)
...
@@ -502,11 +502,19 @@ static void ohci_irq (struct usb_hcd *hcd)
if
((
ohci
->
hcca
->
done_head
!=
0
)
if
((
ohci
->
hcca
->
done_head
!=
0
)
&&
!
(
le32_to_cpup
(
&
ohci
->
hcca
->
done_head
)
&
0x01
))
{
&&
!
(
le32_to_cpup
(
&
ohci
->
hcca
->
done_head
)
&
0x01
))
{
ints
=
OHCI_INTR_WDH
;
ints
=
OHCI_INTR_WDH
;
}
else
if
((
ints
=
(
readl
(
&
regs
->
intrstatus
)
&
readl
(
&
regs
->
intrenable
)))
==
0
)
{
/* cardbus/... hardware gone before remove() */
}
else
if
((
ints
=
readl
(
&
regs
->
intrstatus
))
==
~
(
u32
)
0
)
{
ohci
->
disabled
++
;
err
(
"%s device removed!"
,
hcd
->
self
.
bus_name
);
return
;
/* interrupt for some other device? */
}
else
if
((
ints
&=
readl
(
&
regs
->
intrenable
))
==
0
)
{
return
;
return
;
}
}
// dbg ("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca->frame_no));
// dbg ("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca->frame_no));
if
(
ints
&
OHCI_INTR_UE
)
{
if
(
ints
&
OHCI_INTR_UE
)
{
...
...
drivers/usb/host/uhci-hcd.c
View file @
9cfc20f1
...
@@ -1665,37 +1665,15 @@ static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
...
@@ -1665,37 +1665,15 @@ static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
uhci_unlink_generic
(
uhci
,
urb
);
uhci_unlink_generic
(
uhci
,
urb
);
if
(
urb
->
transfer_flags
&
USB_ASYNC_UNLINK
)
{
spin_lock
(
&
uhci
->
urb_remove_list_lock
);
urbp
->
status
=
urb
->
status
=
-
ECONNABORTED
;
spin_lock
(
&
uhci
->
urb_remove_list_lock
);
/* If we're the first, set the next interrupt bit */
if
(
list_empty
(
&
uhci
->
urb_remove_list
))
/* If we're the first, set the next interrupt bit */
uhci_set_next_interrupt
(
uhci
);
if
(
list_empty
(
&
uhci
->
urb_remove_list
))
list_add
(
&
urbp
->
urb_list
,
&
uhci
->
urb_remove_list
);
uhci_set_next_interrupt
(
uhci
);
list_add
(
&
urbp
->
urb_list
,
&
uhci
->
urb_remove_list
);
spin_unlock
(
&
uhci
->
urb_remove_list_lock
);
spin_unlock_irqrestore
(
&
uhci
->
urb_list_lock
,
flags
);
}
else
{
urb
->
status
=
-
ENOENT
;
spin_unlock_irqrestore
(
&
uhci
->
urb_list_lock
,
flags
);
if
(
in_interrupt
())
{
/* wait at least 1 frame */
static
int
errorcount
=
10
;
if
(
errorcount
--
)
dbg
(
"uhci_urb_dequeue called from interrupt for urb %p"
,
urb
);
udelay
(
1000
);
}
else
schedule_timeout
(
1
+
1
*
HZ
/
1000
);
uhci_finish_urb
(
hcd
,
urb
);
}
spin_unlock
(
&
uhci
->
urb_remove_list_lock
);
spin_unlock_irqrestore
(
&
uhci
->
urb_list_lock
,
flags
);
return
0
;
return
0
;
}
}
...
@@ -1788,7 +1766,7 @@ static void stall_callback(unsigned long ptr)
...
@@ -1788,7 +1766,7 @@ static void stall_callback(unsigned long ptr)
tmp
=
tmp
->
next
;
tmp
=
tmp
->
next
;
u
->
transfer_flags
|=
USB_
ASYNC_UNLINK
|
USB_
TIMEOUT_KILLED
;
u
->
transfer_flags
|=
USB_TIMEOUT_KILLED
;
uhci_urb_dequeue
(
hcd
,
u
);
uhci_urb_dequeue
(
hcd
,
u
);
}
}
...
...
drivers/usb/host/usb-uhci-hcd.c
View file @
9cfc20f1
...
@@ -271,21 +271,15 @@ static int uhci_urb_enqueue (struct usb_hcd *hcd, struct urb *urb, int mem_flags
...
@@ -271,21 +271,15 @@ static int uhci_urb_enqueue (struct usb_hcd *hcd, struct urb *urb, int mem_flags
static
int
uhci_urb_dequeue
(
struct
usb_hcd
*
hcd
,
struct
urb
*
urb
)
static
int
uhci_urb_dequeue
(
struct
usb_hcd
*
hcd
,
struct
urb
*
urb
)
{
{
unsigned
long
flags
=
0
;
unsigned
long
flags
=
0
;
struct
uhci_hcd
*
uhci
;
struct
uhci_hcd
*
uhci
=
hcd_to_uhci
(
hcd
);
int
ret
;
dbg
(
"uhci_urb_dequeue called for %p"
,
urb
);
dbg
(
"uhci_urb_dequeue called for %p"
,
urb
);
uhci
=
hcd_to_uhci
(
hcd
);
spin_lock_irqsave
(
&
uhci
->
urb_list_lock
,
flags
);
ret
=
uhci_unlink_urb_async
(
uhci
,
urb
,
UNLINK_ASYNC_STORE_URB
);
if
(
urb
->
transfer_flags
&
USB_ASYNC_UNLINK
)
{
spin_unlock_irqrestore
(
&
uhci
->
urb_list_lock
,
flags
);
int
ret
;
return
ret
;
spin_lock_irqsave
(
&
uhci
->
urb_list_lock
,
flags
);
ret
=
uhci_unlink_urb_async
(
uhci
,
urb
,
UNLINK_ASYNC_STORE_URB
);
spin_unlock_irqrestore
(
&
uhci
->
urb_list_lock
,
flags
);
return
ret
;
}
else
return
uhci_unlink_urb_sync
(
uhci
,
urb
);
}
}
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/
static
int
uhci_get_frame
(
struct
usb_hcd
*
hcd
)
static
int
uhci_get_frame
(
struct
usb_hcd
*
hcd
)
...
...
drivers/usb/host/usb-uhci-q.c
View file @
9cfc20f1
...
@@ -541,22 +541,6 @@ static void uhci_clean_iso_step1(struct uhci_hcd *uhci, urb_priv_t *urb_priv)
...
@@ -541,22 +541,6 @@ static void uhci_clean_iso_step1(struct uhci_hcd *uhci, urb_priv_t *urb_priv)
}
}
}
}
/*-------------------------------------------------------------------*/
/*-------------------------------------------------------------------*/
static
void
uhci_clean_iso_step2
(
struct
uhci_hcd
*
uhci
,
urb_priv_t
*
urb_priv
)
{
struct
list_head
*
p
;
uhci_desc_t
*
td
;
int
now
=
UHCI_GET_CURRENT_FRAME
(
uhci
);
dbg
(
"uhci_clean_iso_step2"
);
while
((
p
=
urb_priv
->
desc_list
.
next
)
!=
&
urb_priv
->
desc_list
)
{
td
=
list_entry
(
p
,
uhci_desc_t
,
desc_list
);
list_del
(
p
);
INIT_LIST_HEAD
(
&
td
->
horizontal
);
list_add_tail
(
&
td
->
horizontal
,
&
uhci
->
free_desc_td
);
td
->
last_used
=
now
;
}
}
/*-------------------------------------------------------------------*/
/* mode: CLEAN_TRANSFER_NO_DELETION: unlink but no deletion mark (step 1 of async_unlink)
/* mode: CLEAN_TRANSFER_NO_DELETION: unlink but no deletion mark (step 1 of async_unlink)
CLEAN_TRANSFER_REGULAR: regular (unlink/delete-mark)
CLEAN_TRANSFER_REGULAR: regular (unlink/delete-mark)
CLEAN_TRANSFER_DELETION_MARK: deletion mark for QH (step 2 of async_unlink)
CLEAN_TRANSFER_DELETION_MARK: deletion mark for QH (step 2 of async_unlink)
...
@@ -759,44 +743,6 @@ static int uhci_unlink_urb_async (struct uhci_hcd *uhci, struct urb *urb, int mo
...
@@ -759,44 +743,6 @@ static int uhci_unlink_urb_async (struct uhci_hcd *uhci, struct urb *urb, int mo
return
0
;
// completion will follow
return
0
;
// completion will follow
}
}
/*-------------------------------------------------------------------*/
/*-------------------------------------------------------------------*/
// kills an urb by unlinking descriptors and waiting for at least one frame
static
int
uhci_unlink_urb_sync
(
struct
uhci_hcd
*
uhci
,
struct
urb
*
urb
)
{
uhci_desc_t
*
qh
;
urb_priv_t
*
urb_priv
;
unsigned
long
flags
=
0
;
spin_lock_irqsave
(
&
uhci
->
urb_list_lock
,
flags
);
// err("uhci_unlink_urb_sync %p, %i",urb,urb->status);
// move descriptors out the the running chains, dequeue urb
uhci_unlink_urb_async
(
uhci
,
urb
,
UNLINK_ASYNC_DONT_STORE
);
urb_priv
=
urb
->
hcpriv
;
spin_unlock_irqrestore
(
&
uhci
->
urb_list_lock
,
flags
);
// cleanup the rest
switch
(
usb_pipetype
(
urb
->
pipe
))
{
case
PIPE_INTERRUPT
:
case
PIPE_ISOCHRONOUS
:
uhci_wait_ms
(
1
);
uhci_clean_iso_step2
(
uhci
,
urb_priv
);
break
;
case
PIPE_BULK
:
case
PIPE_CONTROL
:
qh
=
list_entry
(
urb_priv
->
desc_list
.
next
,
uhci_desc_t
,
desc_list
);
uhci_clean_transfer
(
uhci
,
urb
,
qh
,
CLEAN_TRANSFER_DELETION_MARK
);
uhci_wait_ms
(
1
);
}
urb
->
status
=
-
ENOENT
;
// mark urb as killed
finish_urb
(
uhci
,
urb
);
return
0
;
}
/*-------------------------------------------------------------------*/
// unlink urbs for specific device or all devices
// unlink urbs for specific device or all devices
static
void
uhci_unlink_urbs
(
struct
uhci_hcd
*
uhci
,
struct
usb_device
*
usb_dev
,
int
remove_all
)
static
void
uhci_unlink_urbs
(
struct
uhci_hcd
*
uhci
,
struct
usb_device
*
usb_dev
,
int
remove_all
)
{
{
...
@@ -816,8 +762,6 @@ static void uhci_unlink_urbs(struct uhci_hcd *uhci, struct usb_device *usb_dev,
...
@@ -816,8 +762,6 @@ static void uhci_unlink_urbs(struct uhci_hcd *uhci, struct usb_device *usb_dev,
// err("unlink urb: %p, dev %p, ud %p", urb, usb_dev,urb->dev);
// err("unlink urb: %p, dev %p, ud %p", urb, usb_dev,urb->dev);
//urb->transfer_flags |=USB_ASYNC_UNLINK;
if
(
remove_all
||
(
usb_dev
==
urb
->
dev
))
{
if
(
remove_all
||
(
usb_dev
==
urb
->
dev
))
{
spin_unlock_irqrestore
(
&
uhci
->
urb_list_lock
,
flags
);
spin_unlock_irqrestore
(
&
uhci
->
urb_list_lock
,
flags
);
err
(
"forced removing of queued URB %p due to disconnect"
,
urb
);
err
(
"forced removing of queued URB %p due to disconnect"
,
urb
);
...
@@ -850,7 +794,7 @@ static void uhci_check_timeouts(struct uhci_hcd *uhci)
...
@@ -850,7 +794,7 @@ static void uhci_check_timeouts(struct uhci_hcd *uhci)
type
=
usb_pipetype
(
urb
->
pipe
);
type
=
usb_pipetype
(
urb
->
pipe
);
if
(
urb
->
timeout
&&
time_after
(
jiffies
,
hcpriv
->
started
+
urb
->
timeout
))
{
if
(
urb
->
timeout
&&
time_after
(
jiffies
,
hcpriv
->
started
+
urb
->
timeout
))
{
urb
->
transfer_flags
|=
USB_TIMEOUT_KILLED
|
USB_ASYNC_UNLINK
;
urb
->
transfer_flags
|=
USB_TIMEOUT_KILLED
;
async_dbg
(
"uhci_check_timeout: timeout for %p"
,
urb
);
async_dbg
(
"uhci_check_timeout: timeout for %p"
,
urb
);
uhci_unlink_urb_async
(
uhci
,
urb
,
UNLINK_ASYNC_STORE_URB
);
uhci_unlink_urb_async
(
uhci
,
urb
,
UNLINK_ASYNC_STORE_URB
);
}
}
...
...
drivers/usb/net/pegasus.c
View file @
9cfc20f1
/*
/*
** Pegasus: USB 10/100Mbps/HomePNA (1Mbps) Controller
* Copyright (c) 1999-2002 Petko Manolov (petkan@users.sourceforge.net)
**
** Copyright (c) 1999-2002 Petko Manolov (petkan@users.sourceforge.net)
**
**
** ChangeLog:
** .... Most of the time spend reading sources & docs.
** v0.2.x First official release for the Linux kernel.
** v0.3.0 Beutified and structured, some bugs fixed.
** v0.3.x URBifying bulk requests and bugfixing. First relatively
** stable release. Still can touch device's registers only
** from top-halves.
** v0.4.0 Control messages remained unurbified are now URBs.
** Now we can touch the HW at any time.
** v0.4.9 Control urbs again use process context to wait. Argh...
** Some long standing bugs (enable_net_traffic) fixed.
** Also nasty trick about resubmiting control urb from
** interrupt context used. Please let me know how it
** behaves. Pegasus II support added since this version.
** TODO: suppressing HCD warnings spewage on disconnect.
** v0.4.13 Ethernet address is now set at probe(), not at open()
** time as this seems to break dhcpd.
** v0.5.0 branch to 2.5.x kernels
** v0.5.1 ethtool support added
*/
/*
* 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 Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
*
* This program is distributed in the hope that it will be useful,
* This program is free software; you can redistribute it and/or modify
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* it under the terms of the GNU General Public License version 2 as
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* published by the Free Software Foundation.
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* ChangeLog:
* along with this program; if not, write to the Free Software
* .... Most of the time spent on reading sources & docs.
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* v0.2.x First official release for the Linux kernel.
* v0.3.0 Beutified and structured, some bugs fixed.
* v0.3.x URBifying bulk requests and bugfixing. First relatively
* stable release. Still can touch device's registers only
* from top-halves.
* v0.4.0 Control messages remained unurbified are now URBs.
* Now we can touch the HW at any time.
* v0.4.9 Control urbs again use process context to wait. Argh...
* Some long standing bugs (enable_net_traffic) fixed.
* Also nasty trick about resubmiting control urb from
* interrupt context used. Please let me know how it
* behaves. Pegasus II support added since this version.
* TODO: suppressing HCD warnings spewage on disconnect.
* v0.4.13 Ethernet address is now set at probe(), not at open()
* time as this seems to break dhcpd.
* v0.5.0 branch to 2.5.x kernels
* v0.5.1 ethtool support added
* v0.5.5 rx socket buffers are in a pool and the their allocation
* is out of the interrupt routine.
*/
*/
#include <linux/sched.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/init.h>
...
@@ -58,14 +46,13 @@
...
@@ -58,14 +46,13 @@
/*
/*
* Version Information
* Version Information
*/
*/
#define DRIVER_VERSION "v0.5.
4 (2002/04/11
)"
#define DRIVER_VERSION "v0.5.
6 (2002/06/23
)"
#define DRIVER_AUTHOR "Petko Manolov <petkan@users.sourceforge.net>"
#define DRIVER_AUTHOR "Petko Manolov <petkan@users.sourceforge.net>"
#define DRIVER_DESC "Pegasus/Pegasus II USB Ethernet driver"
#define DRIVER_DESC "Pegasus/Pegasus II USB Ethernet driver"
static
const
char
driver_name
[]
=
"pegasus"
;
static
const
char
driver_name
[]
=
"pegasus"
;
#define PEGASUS_USE_INTR
#undef PEGASUS_WRITE_EEPROM
#define PEGASUS_WRITE_EEPROM
#define BMSR_MEDIA (BMSR_10HALF | BMSR_10FULL | BMSR_100HALF | \
#define BMSR_MEDIA (BMSR_10HALF | BMSR_10FULL | BMSR_100HALF | \
BMSR_100FULL | BMSR_ANEGCAPABLE)
BMSR_100FULL | BMSR_ANEGCAPABLE)
...
@@ -499,13 +486,57 @@ static int enable_net_traffic(struct net_device *dev, struct usb_device *usb)
...
@@ -499,13 +486,57 @@ static int enable_net_traffic(struct net_device *dev, struct usb_device *usb)
return
0
;
return
0
;
}
}
static
void
fill_skb_pool
(
pegasus_t
*
pegasus
)
{
int
i
;
for
(
i
=
0
;
i
<
RX_SKBS
;
i
++
)
{
if
(
pegasus
->
rx_pool
[
i
])
continue
;
pegasus
->
rx_pool
[
i
]
=
dev_alloc_skb
(
PEGASUS_MTU
+
2
);
/*
** we give up if the allocation fail. the tasklet will be
** rescheduled again anyway...
*/
if
(
pegasus
->
rx_pool
[
i
]
==
NULL
)
return
;
pegasus
->
rx_pool
[
i
]
->
dev
=
pegasus
->
net
;
skb_reserve
(
pegasus
->
rx_pool
[
i
],
2
);
}
}
static
void
free_skb_pool
(
pegasus_t
*
pegasus
)
{
int
i
;
for
(
i
=
0
;
i
<
RX_SKBS
;
i
++
)
{
if
(
pegasus
->
rx_pool
[
i
])
{
dev_kfree_skb
(
pegasus
->
rx_pool
[
i
]);
pegasus
->
rx_pool
[
i
]
=
NULL
;
}
}
}
static
inline
struct
sk_buff
*
pull_skb
(
pegasus_t
*
pegasus
)
{
int
i
;
struct
sk_buff
*
skb
;
for
(
i
=
0
;
i
<
RX_SKBS
;
i
++
)
{
if
(
likely
(
pegasus
->
rx_pool
[
i
]
!=
NULL
))
{
skb
=
pegasus
->
rx_pool
[
i
];
pegasus
->
rx_pool
[
i
]
=
NULL
;
return
skb
;
}
}
return
NULL
;
}
static
void
read_bulk_callback
(
struct
urb
*
urb
)
static
void
read_bulk_callback
(
struct
urb
*
urb
)
{
{
pegasus_t
*
pegasus
=
urb
->
context
;
pegasus_t
*
pegasus
=
urb
->
context
;
struct
net_device
*
net
;
struct
net_device
*
net
;
int
count
=
urb
->
actual_length
;
int
rx_status
,
count
=
urb
->
actual_length
;
int
rx_status
;
struct
sk_buff
*
skb
;
__u16
pkt_len
;
__u16
pkt_len
;
if
(
!
pegasus
||
!
(
pegasus
->
flags
&
PEGASUS_RUNNING
))
if
(
!
pegasus
||
!
(
pegasus
->
flags
&
PEGASUS_RUNNING
))
...
@@ -519,7 +550,7 @@ static void read_bulk_callback(struct urb *urb)
...
@@ -519,7 +550,7 @@ static void read_bulk_callback(struct urb *urb)
case
0
:
case
0
:
break
;
break
;
case
-
ETIMEDOUT
:
case
-
ETIMEDOUT
:
dbg
(
"
reset MAC"
);
dbg
(
"
%s: reset MAC"
,
net
->
name
);
pegasus
->
flags
&=
~
PEGASUS_RX_BUSY
;
pegasus
->
flags
&=
~
PEGASUS_RX_BUSY
;
break
;
break
;
case
-
ENOENT
:
case
-
ENOENT
:
...
@@ -546,23 +577,24 @@ static void read_bulk_callback(struct urb *urb)
...
@@ -546,23 +577,24 @@ static void read_bulk_callback(struct urb *urb)
}
}
pkt_len
=
(
rx_status
&
0xfff
)
-
8
;
pkt_len
=
(
rx_status
&
0xfff
)
-
8
;
if
(
!
pegasus
->
rx_skb
)
if
(
pegasus
->
rx_skb
==
NULL
)
goto
tl_sched
;
printk
(
"%s: rx_skb == NULL
\n
"
,
__FUNCTION__
);
/*
** we are sure at this point pegasus->rx_skb != NULL
** so we go ahead and pass up the packet.
*/
skb_put
(
pegasus
->
rx_skb
,
pkt_len
);
skb_put
(
pegasus
->
rx_skb
,
pkt_len
);
pegasus
->
rx_skb
->
protocol
=
eth_type_trans
(
pegasus
->
rx_skb
,
net
);
pegasus
->
rx_skb
->
protocol
=
eth_type_trans
(
pegasus
->
rx_skb
,
net
);
netif_rx
(
pegasus
->
rx_skb
);
netif_rx
(
pegasus
->
rx_skb
);
if
(
!
(
skb
=
dev_alloc_skb
(
PEGASUS_MTU
+
2
)))
{
pegasus
->
rx_skb
=
NULL
;
goto
tl_sched
;
}
skb
->
dev
=
net
;
skb_reserve
(
skb
,
2
);
pegasus
->
rx_skb
=
skb
;
pegasus
->
stats
.
rx_packets
++
;
pegasus
->
stats
.
rx_packets
++
;
pegasus
->
stats
.
rx_bytes
+=
pkt_len
;
pegasus
->
stats
.
rx_bytes
+=
pkt_len
;
spin_lock
(
&
pegasus
->
rx_pool_lock
);
pegasus
->
rx_skb
=
pull_skb
(
pegasus
);
spin_unlock
(
&
pegasus
->
rx_pool_lock
);
if
(
pegasus
->
rx_skb
==
NULL
)
goto
tl_sched
;
goon:
goon:
FILL_BULK_URB
(
pegasus
->
rx_urb
,
pegasus
->
usb
,
FILL_BULK_URB
(
pegasus
->
rx_urb
,
pegasus
->
usb
,
usb_rcvbulkpipe
(
pegasus
->
usb
,
1
),
usb_rcvbulkpipe
(
pegasus
->
usb
,
1
),
...
@@ -587,11 +619,19 @@ static void rx_fixup(unsigned long data)
...
@@ -587,11 +619,19 @@ static void rx_fixup(unsigned long data)
pegasus
=
(
pegasus_t
*
)
data
;
pegasus
=
(
pegasus_t
*
)
data
;
spin_lock_irq
(
&
pegasus
->
rx_pool_lock
);
fill_skb_pool
(
pegasus
);
spin_unlock_irq
(
&
pegasus
->
rx_pool_lock
);
if
(
pegasus
->
flags
&
PEGASUS_RX_URB_FAIL
)
if
(
pegasus
->
flags
&
PEGASUS_RX_URB_FAIL
)
if
(
pegasus
->
rx_skb
)
if
(
pegasus
->
rx_skb
)
goto
try_again
;
goto
try_again
;
if
(
pegasus
->
rx_skb
==
NULL
)
{
if
(
!
(
pegasus
->
rx_skb
=
dev_alloc_skb
(
PEGASUS_MTU
+
2
)))
{
spin_lock_irq
(
&
pegasus
->
rx_pool_lock
);
pegasus
->
rx_skb
=
pull_skb
(
pegasus
);
spin_unlock_irq
(
&
pegasus
->
rx_pool_lock
);
}
if
(
pegasus
->
rx_skb
==
NULL
)
{
warn
(
"wow, low on memory"
);
tasklet_schedule
(
&
pegasus
->
rx_tl
);
tasklet_schedule
(
&
pegasus
->
rx_tl
);
return
;
return
;
}
}
...
@@ -625,7 +665,6 @@ static void write_bulk_callback(struct urb *urb)
...
@@ -625,7 +665,6 @@ static void write_bulk_callback(struct urb *urb)
netif_wake_queue
(
pegasus
->
net
);
netif_wake_queue
(
pegasus
->
net
);
}
}
#ifdef PEGASUS_USE_INTR
static
void
intr_callback
(
struct
urb
*
urb
)
static
void
intr_callback
(
struct
urb
*
urb
)
{
{
pegasus_t
*
pegasus
=
urb
->
context
;
pegasus_t
*
pegasus
=
urb
->
context
;
...
@@ -662,7 +701,6 @@ static void intr_callback(struct urb *urb)
...
@@ -662,7 +701,6 @@ static void intr_callback(struct urb *urb)
}
}
}
}
}
}
#endif
static
void
pegasus_tx_timeout
(
struct
net_device
*
net
)
static
void
pegasus_tx_timeout
(
struct
net_device
*
net
)
{
{
...
@@ -748,15 +786,62 @@ static void set_carrier(struct net_device *net)
...
@@ -748,15 +786,62 @@ static void set_carrier(struct net_device *net)
}
}
static
void
free_all_urbs
(
pegasus_t
*
pegasus
)
{
usb_free_urb
(
pegasus
->
intr_urb
);
usb_free_urb
(
pegasus
->
tx_urb
);
usb_free_urb
(
pegasus
->
rx_urb
);
usb_free_urb
(
pegasus
->
ctrl_urb
);
}
static
void
unlink_all_urbs
(
pegasus_t
*
pegasus
)
{
usb_unlink_urb
(
pegasus
->
intr_urb
);
usb_unlink_urb
(
pegasus
->
tx_urb
);
usb_unlink_urb
(
pegasus
->
rx_urb
);
usb_unlink_urb
(
pegasus
->
ctrl_urb
);
}
static
int
alloc_urbs
(
pegasus_t
*
pegasus
)
{
pegasus
->
ctrl_urb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
if
(
!
pegasus
->
ctrl_urb
)
{
return
0
;
}
pegasus
->
rx_urb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
if
(
!
pegasus
->
rx_urb
)
{
usb_free_urb
(
pegasus
->
ctrl_urb
);
return
0
;
}
pegasus
->
tx_urb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
if
(
!
pegasus
->
tx_urb
)
{
usb_free_urb
(
pegasus
->
rx_urb
);
usb_free_urb
(
pegasus
->
ctrl_urb
);
return
0
;
}
pegasus
->
intr_urb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
if
(
!
pegasus
->
intr_urb
)
{
usb_free_urb
(
pegasus
->
tx_urb
);
usb_free_urb
(
pegasus
->
rx_urb
);
usb_free_urb
(
pegasus
->
ctrl_urb
);
return
0
;
}
return
1
;
}
static
int
pegasus_open
(
struct
net_device
*
net
)
static
int
pegasus_open
(
struct
net_device
*
net
)
{
{
pegasus_t
*
pegasus
=
(
pegasus_t
*
)
net
->
priv
;
pegasus_t
*
pegasus
=
(
pegasus_t
*
)
net
->
priv
;
int
res
;
int
res
;
if
(
!
(
pegasus
->
rx_skb
=
dev_alloc_skb
(
PEGASUS_MTU
+
2
)))
if
(
pegasus
->
rx_skb
==
NULL
)
pegasus
->
rx_skb
=
pull_skb
(
pegasus
);
/*
** Note: no point to free the pool. it is empty :-)
*/
if
(
!
pegasus
->
rx_skb
)
return
-
ENOMEM
;
return
-
ENOMEM
;
pegasus
->
rx_skb
->
dev
=
net
;
skb_reserve
(
pegasus
->
rx_skb
,
2
);
down
(
&
pegasus
->
sem
);
down
(
&
pegasus
->
sem
);
FILL_BULK_URB
(
pegasus
->
rx_urb
,
pegasus
->
usb
,
FILL_BULK_URB
(
pegasus
->
rx_urb
,
pegasus
->
usb
,
...
@@ -765,19 +850,20 @@ static int pegasus_open(struct net_device *net)
...
@@ -765,19 +850,20 @@ static int pegasus_open(struct net_device *net)
read_bulk_callback
,
pegasus
);
read_bulk_callback
,
pegasus
);
if
((
res
=
usb_submit_urb
(
pegasus
->
rx_urb
,
GFP_KERNEL
)))
if
((
res
=
usb_submit_urb
(
pegasus
->
rx_urb
,
GFP_KERNEL
)))
warn
(
"%s: failed rx_urb %d"
,
__FUNCTION__
,
res
);
warn
(
"%s: failed rx_urb %d"
,
__FUNCTION__
,
res
);
#ifdef PEGASUS_USE_INTR
FILL_INT_URB
(
pegasus
->
intr_urb
,
pegasus
->
usb
,
FILL_INT_URB
(
pegasus
->
intr_urb
,
pegasus
->
usb
,
usb_rcvintpipe
(
pegasus
->
usb
,
3
),
usb_rcvintpipe
(
pegasus
->
usb
,
3
),
pegasus
->
intr_buff
,
sizeof
(
pegasus
->
intr_buff
),
pegasus
->
intr_buff
,
sizeof
(
pegasus
->
intr_buff
),
intr_callback
,
pegasus
,
pegasus
->
intr_interval
);
intr_callback
,
pegasus
,
pegasus
->
intr_interval
);
if
((
res
=
usb_submit_urb
(
pegasus
->
intr_urb
,
GFP_KERNEL
)))
if
((
res
=
usb_submit_urb
(
pegasus
->
intr_urb
,
GFP_KERNEL
)))
warn
(
"%s: failed intr_urb %d"
,
__FUNCTION__
,
res
);
warn
(
"%s: failed intr_urb %d"
,
__FUNCTION__
,
res
);
#endif
netif_start_queue
(
net
);
netif_start_queue
(
net
);
pegasus
->
flags
|=
PEGASUS_RUNNING
;
pegasus
->
flags
|=
PEGASUS_RUNNING
;
if
((
res
=
enable_net_traffic
(
net
,
pegasus
->
usb
)))
{
if
((
res
=
enable_net_traffic
(
net
,
pegasus
->
usb
)))
{
err
(
"can't enable_net_traffic() - %d"
,
res
);
err
(
"can't enable_net_traffic() - %d"
,
res
);
res
=
-
EIO
;
res
=
-
EIO
;
usb_unlink_urb
(
pegasus
->
rx_urb
);
usb_unlink_urb
(
pegasus
->
intr_urb
);
free_skb_pool
(
pegasus
);
goto
exit
;
goto
exit
;
}
}
set_carrier
(
net
);
set_carrier
(
net
);
...
@@ -797,13 +883,7 @@ static int pegasus_close(struct net_device *net)
...
@@ -797,13 +883,7 @@ static int pegasus_close(struct net_device *net)
netif_stop_queue
(
net
);
netif_stop_queue
(
net
);
if
(
!
(
pegasus
->
flags
&
PEGASUS_UNPLUG
))
if
(
!
(
pegasus
->
flags
&
PEGASUS_UNPLUG
))
disable_net_traffic
(
pegasus
);
disable_net_traffic
(
pegasus
);
unlink_all_urbs
(
pegasus
);
usb_unlink_urb
(
pegasus
->
rx_urb
);
usb_unlink_urb
(
pegasus
->
tx_urb
);
usb_unlink_urb
(
pegasus
->
ctrl_urb
);
#ifdef PEGASUS_USE_INTR
usb_unlink_urb
(
pegasus
->
intr_urb
);
#endif
up
(
&
pegasus
->
sem
);
up
(
&
pegasus
->
sem
);
return
0
;
return
0
;
...
@@ -986,38 +1066,14 @@ static void *pegasus_probe(struct usb_device *dev, unsigned int ifnum,
...
@@ -986,38 +1066,14 @@ static void *pegasus_probe(struct usb_device *dev, unsigned int ifnum,
pegasus
->
dev_index
=
dev_index
;
pegasus
->
dev_index
=
dev_index
;
init_waitqueue_head
(
&
pegasus
->
ctrl_wait
);
init_waitqueue_head
(
&
pegasus
->
ctrl_wait
);
pegasus
->
ctrl_urb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
if
(
!
alloc_urbs
(
pegasus
))
{
if
(
!
pegasus
->
ctrl_urb
)
{
kfree
(
pegasus
);
return
NULL
;
}
pegasus
->
rx_urb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
if
(
!
pegasus
->
rx_urb
)
{
usb_free_urb
(
pegasus
->
ctrl_urb
);
kfree
(
pegasus
);
return
NULL
;
}
pegasus
->
tx_urb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
if
(
!
pegasus
->
tx_urb
)
{
usb_free_urb
(
pegasus
->
rx_urb
);
usb_free_urb
(
pegasus
->
ctrl_urb
);
kfree
(
pegasus
);
return
NULL
;
}
pegasus
->
intr_urb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
if
(
!
pegasus
->
intr_urb
)
{
usb_free_urb
(
pegasus
->
tx_urb
);
usb_free_urb
(
pegasus
->
rx_urb
);
usb_free_urb
(
pegasus
->
ctrl_urb
);
kfree
(
pegasus
);
kfree
(
pegasus
);
return
NULL
;
return
NULL
;
}
}
net
=
init_etherdev
(
NULL
,
0
);
net
=
init_etherdev
(
NULL
,
0
);
if
(
!
net
)
{
if
(
!
net
)
{
usb_free_urb
(
pegasus
->
tx_urb
);
free_all_urbs
(
pegasus
);
usb_free_urb
(
pegasus
->
rx_urb
);
usb_free_urb
(
pegasus
->
ctrl_urb
);
kfree
(
pegasus
);
kfree
(
pegasus
);
return
NULL
;
return
NULL
;
}
}
...
@@ -1039,32 +1095,26 @@ static void *pegasus_probe(struct usb_device *dev, unsigned int ifnum,
...
@@ -1039,32 +1095,26 @@ static void *pegasus_probe(struct usb_device *dev, unsigned int ifnum,
net
->
set_multicast_list
=
pegasus_set_multicast
;
net
->
set_multicast_list
=
pegasus_set_multicast
;
net
->
get_stats
=
pegasus_netdev_stats
;
net
->
get_stats
=
pegasus_netdev_stats
;
net
->
mtu
=
PEGASUS_MTU
;
net
->
mtu
=
PEGASUS_MTU
;
spin_lock_init
(
&
pegasus
->
rx_pool_lock
);
pegasus
->
features
=
usb_dev_id
[
dev_index
].
private
;
pegasus
->
features
=
usb_dev_id
[
dev_index
].
private
;
#ifdef PEGASUS_USE_INTR
get_interrupt_interval
(
pegasus
);
get_interrupt_interval
(
pegasus
);
#endif
if
(
reset_mac
(
pegasus
))
{
if
(
reset_mac
(
pegasus
))
{
err
(
"can't reset MAC"
);
err
(
"can't reset MAC"
);
unregister_netdev
(
pegasus
->
net
);
unregister_netdev
(
pegasus
->
net
);
usb_free_urb
(
pegasus
->
tx_urb
);
free_all_urbs
(
pegasus
);
usb_free_urb
(
pegasus
->
rx_urb
);
usb_free_urb
(
pegasus
->
ctrl_urb
);
kfree
(
pegasus
->
net
);
kfree
(
pegasus
->
net
);
kfree
(
pegasus
);
kfree
(
pegasus
);
pegasus
=
NULL
;
pegasus
=
NULL
;
goto
exit
;
goto
exit
;
}
}
info
(
"%s: %s"
,
net
->
name
,
usb_dev_id
[
dev_index
].
name
);
set_ethernet_addr
(
pegasus
);
set_ethernet_addr
(
pegasus
);
fill_skb_pool
(
pegasus
);
printk
(
"%s: %s
\n
"
,
net
->
name
,
usb_dev_id
[
dev_index
].
name
);
if
(
pegasus
->
features
&
PEGASUS_II
)
{
if
(
pegasus
->
features
&
PEGASUS_II
)
{
info
(
"setup Pegasus II specific registers"
);
info
(
"setup Pegasus II specific registers"
);
setup_pegasus_II
(
pegasus
);
setup_pegasus_II
(
pegasus
);
}
}
pegasus
->
phy
=
mii_phy_probe
(
pegasus
);
pegasus
->
phy
=
mii_phy_probe
(
pegasus
);
if
(
pegasus
->
phy
==
0xff
)
{
if
(
pegasus
->
phy
==
0xff
)
{
warn
(
"can't locate MII phy, using default"
);
warn
(
"can't locate MII phy, using default"
);
...
@@ -1087,14 +1137,9 @@ static void pegasus_disconnect(struct usb_device *dev, void *ptr)
...
@@ -1087,14 +1137,9 @@ static void pegasus_disconnect(struct usb_device *dev, void *ptr)
pegasus
->
flags
|=
PEGASUS_UNPLUG
;
pegasus
->
flags
|=
PEGASUS_UNPLUG
;
unregister_netdev
(
pegasus
->
net
);
unregister_netdev
(
pegasus
->
net
);
usb_put_dev
(
dev
);
usb_put_dev
(
dev
);
usb_unlink_urb
(
pegasus
->
intr_urb
);
unlink_all_urbs
(
pegasus
);
usb_unlink_urb
(
pegasus
->
tx_urb
);
free_all_urbs
(
pegasus
);
usb_unlink_urb
(
pegasus
->
rx_urb
);
free_skb_pool
(
pegasus
);
usb_unlink_urb
(
pegasus
->
ctrl_urb
);
usb_free_urb
(
pegasus
->
intr_urb
);
usb_free_urb
(
pegasus
->
tx_urb
);
usb_free_urb
(
pegasus
->
rx_urb
);
usb_free_urb
(
pegasus
->
ctrl_urb
);
if
(
pegasus
->
rx_skb
)
if
(
pegasus
->
rx_skb
)
dev_kfree_skb
(
pegasus
->
rx_skb
);
dev_kfree_skb
(
pegasus
->
rx_skb
);
kfree
(
pegasus
->
net
);
kfree
(
pegasus
->
net
);
...
...
drivers/usb/net/pegasus.h
View file @
9cfc20f1
...
@@ -2,18 +2,8 @@
...
@@ -2,18 +2,8 @@
* Copyright (c) 1999-2002 Petko Manolov - Petkan (petkan@users.sourceforge.net)
* Copyright (c) 1999-2002 Petko Manolov - Petkan (petkan@users.sourceforge.net)
*
*
* This program is free software; you can redistribute it and/or modify
* 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
* it under the terms of the GNU General Public License version 2 as published
* the Free Software Foundation; either version 2 of the License, or
* by the Free Software Foundation.
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
*/
...
@@ -23,6 +13,7 @@
...
@@ -23,6 +13,7 @@
#define HAS_HOME_PNA 0x40000000
#define HAS_HOME_PNA 0x40000000
#define PEGASUS_MTU 1536
#define PEGASUS_MTU 1536
#define RX_SKBS 4
#define EPROM_WRITE 0x01
#define EPROM_WRITE 0x01
#define EPROM_READ 0x02
#define EPROM_READ 0x02
...
@@ -100,10 +91,12 @@ typedef struct pegasus {
...
@@ -100,10 +91,12 @@ typedef struct pegasus {
int
intr_interval
;
int
intr_interval
;
struct
tasklet_struct
rx_tl
;
struct
tasklet_struct
rx_tl
;
struct
urb
*
ctrl_urb
,
*
rx_urb
,
*
tx_urb
,
*
intr_urb
;
struct
urb
*
ctrl_urb
,
*
rx_urb
,
*
tx_urb
,
*
intr_urb
;
struct
sk_buff
*
rx_pool
[
RX_SKBS
];
struct
sk_buff
*
rx_skb
;
struct
sk_buff
*
rx_skb
;
struct
usb_ctrlrequest
dr
;
struct
usb_ctrlrequest
dr
;
wait_queue_head_t
ctrl_wait
;
wait_queue_head_t
ctrl_wait
;
struct
semaphore
sem
;
struct
semaphore
sem
;
spinlock_t
rx_pool_lock
;
unsigned
char
intr_buff
[
8
];
unsigned
char
intr_buff
[
8
];
__u8
tx_buff
[
PEGASUS_MTU
];
__u8
tx_buff
[
PEGASUS_MTU
];
__u8
eth_regs
[
4
];
__u8
eth_regs
[
4
];
...
...
drivers/usb/net/rtl8150.c
View file @
9cfc20f1
/*
/*
* Copyright (c) 2002 Petko Manolov (petkan@users.sourceforge.net)
* Copyright (c) 2002 Petko Manolov (petkan@users.sourceforge.net)
*
* 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 Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*/
*/
#include <linux/config.h>
#include <linux/config.h>
#include <linux/sched.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/signal.h>
#include <linux/signal.h>
#include <linux/slab.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/module.h>
...
@@ -19,7 +18,6 @@
...
@@ -19,7 +18,6 @@
#include <linux/ethtool.h>
#include <linux/ethtool.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/usb.h>
#include <linux/usb.h>
#include <linux/init.h>
#include <asm/uaccess.h>
#include <asm/uaccess.h>
/* Version Information */
/* Version Information */
...
@@ -106,7 +104,7 @@ unsigned long multicast_filter_limit = 32;
...
@@ -106,7 +104,7 @@ unsigned long multicast_filter_limit = 32;
static
void
fill_skb_pool
(
rtl8150_t
*
);
static
void
fill_skb_pool
(
rtl8150_t
*
);
static
void
free_skb_pool
(
rtl8150_t
*
);
static
void
free_skb_pool
(
rtl8150_t
*
);
static
struct
sk_buff
*
pull_skb
(
rtl8150_t
*
);
static
inline
struct
sk_buff
*
pull_skb
(
rtl8150_t
*
);
static
void
rtl8150_disconnect
(
struct
usb_device
*
dev
,
void
*
ptr
);
static
void
rtl8150_disconnect
(
struct
usb_device
*
dev
,
void
*
ptr
);
static
void
*
rtl8150_probe
(
struct
usb_device
*
dev
,
unsigned
int
ifnum
,
static
void
*
rtl8150_probe
(
struct
usb_device
*
dev
,
unsigned
int
ifnum
,
const
struct
usb_device_id
*
id
);
const
struct
usb_device_id
*
id
);
...
@@ -312,7 +310,7 @@ static void read_bulk_callback(struct urb *urb)
...
@@ -312,7 +310,7 @@ static void read_bulk_callback(struct urb *urb)
case
-
ENOENT
:
case
-
ENOENT
:
return
;
/* the urb is in unlink state */
return
;
/* the urb is in unlink state */
case
-
ETIMEDOUT
:
case
-
ETIMEDOUT
:
warn
(
"
reset needed may be
?.."
);
warn
(
"
may be reset is needed
?.."
);
goto
goon
;
goto
goon
;
default:
default:
warn
(
"Rx status %d"
,
urb
->
status
);
warn
(
"Rx status %d"
,
urb
->
status
);
...
@@ -331,13 +329,13 @@ static void read_bulk_callback(struct urb *urb)
...
@@ -331,13 +329,13 @@ static void read_bulk_callback(struct urb *urb)
netif_rx
(
dev
->
rx_skb
);
netif_rx
(
dev
->
rx_skb
);
dev
->
stats
.
rx_packets
++
;
dev
->
stats
.
rx_packets
++
;
dev
->
stats
.
rx_bytes
+=
pkt_len
;
dev
->
stats
.
rx_bytes
+=
pkt_len
;
spin_lock
(
&
dev
->
rx_pool_lock
);
skb
=
pull_skb
(
dev
);
skb
=
pull_skb
(
dev
);
spin_unlock
(
&
dev
->
rx_pool_lock
);
if
(
!
skb
)
if
(
!
skb
)
goto
resched
;
goto
resched
;
skb
->
dev
=
netdev
;
skb_reserve
(
skb
,
2
);
dev
->
rx_skb
=
skb
;
dev
->
rx_skb
=
skb
;
goon:
goon:
FILL_BULK_URB
(
dev
->
rx_urb
,
dev
->
udev
,
usb_rcvbulkpipe
(
dev
->
udev
,
1
),
FILL_BULK_URB
(
dev
->
rx_urb
,
dev
->
udev
,
usb_rcvbulkpipe
(
dev
->
udev
,
1
),
...
@@ -361,11 +359,16 @@ static void rx_fixup(unsigned long data)
...
@@ -361,11 +359,16 @@ static void rx_fixup(unsigned long data)
dev
=
(
rtl8150_t
*
)
data
;
dev
=
(
rtl8150_t
*
)
data
;
spin_lock_irq
(
&
dev
->
rx_pool_lock
);
fill_skb_pool
(
dev
);
fill_skb_pool
(
dev
);
spin_unlock_irq
(
&
dev
->
rx_pool_lock
);
if
(
test_bit
(
RX_URB_FAIL
,
&
dev
->
flags
))
if
(
test_bit
(
RX_URB_FAIL
,
&
dev
->
flags
))
if
(
dev
->
rx_skb
)
if
(
dev
->
rx_skb
)
goto
try_again
;
goto
try_again
;
if
(
!
(
skb
=
pull_skb
(
dev
)))
spin_lock_irq
(
&
dev
->
rx_pool_lock
);
skb
=
pull_skb
(
dev
);
spin_unlock_irq
(
&
dev
->
rx_pool_lock
);
if
(
skb
==
NULL
)
goto
tlsched
;
goto
tlsched
;
dev
->
rx_skb
=
skb
;
dev
->
rx_skb
=
skb
;
FILL_BULK_URB
(
dev
->
rx_urb
,
dev
->
udev
,
usb_rcvbulkpipe
(
dev
->
udev
,
1
),
FILL_BULK_URB
(
dev
->
rx_urb
,
dev
->
udev
,
usb_rcvbulkpipe
(
dev
->
udev
,
1
),
...
@@ -426,51 +429,41 @@ static void fill_skb_pool(rtl8150_t *dev)
...
@@ -426,51 +429,41 @@ static void fill_skb_pool(rtl8150_t *dev)
{
{
struct
sk_buff
*
skb
;
struct
sk_buff
*
skb
;
int
i
;
int
i
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
dev
->
rx_pool_lock
,
flags
);
for
(
i
=
0
;
i
<
RX_SKB_POOL_SIZE
;
i
++
)
{
for
(
i
=
0
;
i
<
RX_SKB_POOL_SIZE
;
i
++
)
{
if
(
dev
->
rx_skb_pool
[
i
])
if
(
dev
->
rx_skb_pool
[
i
])
continue
;
continue
;
skb
=
dev_alloc_skb
(
RTL8150_MTU
+
2
);
skb
=
dev_alloc_skb
(
RTL8150_MTU
+
2
);
if
(
!
skb
)
{
if
(
!
skb
)
{
spin_unlock_irqrestore
(
&
dev
->
rx_pool_lock
,
flags
);
return
;
return
;
}
}
skb
->
dev
=
dev
->
netdev
;
skb
->
dev
=
dev
->
netdev
;
skb_reserve
(
skb
,
2
);
skb_reserve
(
skb
,
2
);
dev
->
rx_skb_pool
[
i
]
=
skb
;
dev
->
rx_skb_pool
[
i
]
=
skb
;
}
}
spin_unlock_irqrestore
(
&
dev
->
rx_pool_lock
,
flags
);
}
}
static
void
free_skb_pool
(
rtl8150_t
*
dev
)
static
void
free_skb_pool
(
rtl8150_t
*
dev
)
{
{
int
i
;
int
i
;
spin_lock_irq
(
&
dev
->
rx_pool_lock
);
for
(
i
=
0
;
i
<
RX_SKB_POOL_SIZE
;
i
++
)
for
(
i
=
0
;
i
<
RX_SKB_POOL_SIZE
;
i
++
)
if
(
dev
->
rx_skb_pool
[
i
])
if
(
dev
->
rx_skb_pool
[
i
])
dev_kfree_skb
(
dev
->
rx_skb_pool
[
i
]);
dev_kfree_skb
(
dev
->
rx_skb_pool
[
i
]);
spin_unlock_irq
(
&
dev
->
rx_pool_lock
);
}
}
static
struct
sk_buff
*
pull_skb
(
rtl8150_t
*
dev
)
static
inline
struct
sk_buff
*
pull_skb
(
rtl8150_t
*
dev
)
{
{
struct
sk_buff
*
skb
;
struct
sk_buff
*
skb
;
int
i
;
int
i
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
dev
->
rx_pool_lock
,
flags
);
for
(
i
=
0
;
i
<
RX_SKB_POOL_SIZE
;
i
++
)
{
for
(
i
=
0
;
i
<
RX_SKB_POOL_SIZE
;
i
++
)
{
if
(
dev
->
rx_skb_pool
[
i
])
{
if
(
dev
->
rx_skb_pool
[
i
])
{
skb
=
dev
->
rx_skb_pool
[
i
];
skb
=
dev
->
rx_skb_pool
[
i
];
dev
->
rx_skb_pool
[
i
]
=
NULL
;
dev
->
rx_skb_pool
[
i
]
=
NULL
;
spin_unlock_irqrestore
(
&
dev
->
rx_pool_lock
,
flags
);
return
skb
;
return
skb
;
}
}
}
}
spin_unlock_irqrestore
(
&
dev
->
rx_pool_lock
,
flags
);
return
NULL
;
return
NULL
;
}
}
...
@@ -578,8 +571,8 @@ static int rtl8150_open(struct net_device *netdev)
...
@@ -578,8 +571,8 @@ static int rtl8150_open(struct net_device *netdev)
if
(
dev
==
NULL
)
{
if
(
dev
==
NULL
)
{
return
-
ENODEV
;
return
-
ENODEV
;
}
}
if
(
dev
->
rx_skb
==
NULL
)
dev
->
rx_skb
=
pull_skb
(
dev
);
dev
->
rx_skb
=
pull_skb
(
dev
);
if
(
!
dev
->
rx_skb
)
if
(
!
dev
->
rx_skb
)
return
-
ENOMEM
;
return
-
ENOMEM
;
...
@@ -816,13 +809,13 @@ static void rtl8150_disconnect(struct usb_device *udev, void *ptr)
...
@@ -816,13 +809,13 @@ static void rtl8150_disconnect(struct usb_device *udev, void *ptr)
dev
=
NULL
;
dev
=
NULL
;
}
}
static
int
__init
usb_rtl8150_init
(
void
)
int
__init
usb_rtl8150_init
(
void
)
{
{
info
(
DRIVER_DESC
" "
DRIVER_VERSION
);
info
(
DRIVER_DESC
" "
DRIVER_VERSION
);
return
usb_register
(
&
rtl8150_driver
);
return
usb_register
(
&
rtl8150_driver
);
}
}
static
void
__exit
usb_rtl8150_exit
(
void
)
void
__exit
usb_rtl8150_exit
(
void
)
{
{
usb_deregister
(
&
rtl8150_driver
);
usb_deregister
(
&
rtl8150_driver
);
}
}
...
...
drivers/usb/storage/transport.c
View file @
9cfc20f1
...
@@ -428,18 +428,13 @@ int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
...
@@ -428,18 +428,13 @@ int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
void
*
data
,
u16
size
)
void
*
data
,
u16
size
)
{
{
int
status
;
int
status
;
struct
usb_ctrlrequest
*
dr
;
dr
=
kmalloc
(
sizeof
(
struct
usb_ctrlrequest
),
GFP_NOIO
);
if
(
!
dr
)
return
-
ENOMEM
;
/* fill in the devrequest structure */
/* fill in the devrequest structure */
dr
->
bRequestType
=
requesttype
;
us
->
dr
->
bRequestType
=
requesttype
;
dr
->
bRequest
=
request
;
us
->
dr
->
bRequest
=
request
;
dr
->
wValue
=
cpu_to_le16
(
value
);
us
->
dr
->
wValue
=
cpu_to_le16
(
value
);
dr
->
wIndex
=
cpu_to_le16
(
index
);
us
->
dr
->
wIndex
=
cpu_to_le16
(
index
);
dr
->
wLength
=
cpu_to_le16
(
size
);
us
->
dr
->
wLength
=
cpu_to_le16
(
size
);
/* lock the URB */
/* lock the URB */
down
(
&
(
us
->
current_urb_sem
));
down
(
&
(
us
->
current_urb_sem
));
...
@@ -452,7 +447,7 @@ int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
...
@@ -452,7 +447,7 @@ int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
/* fill the URB */
/* fill the URB */
FILL_CONTROL_URB
(
us
->
current_urb
,
us
->
pusb_dev
,
pipe
,
FILL_CONTROL_URB
(
us
->
current_urb
,
us
->
pusb_dev
,
pipe
,
(
unsigned
char
*
)
dr
,
data
,
size
,
(
unsigned
char
*
)
us
->
dr
,
data
,
size
,
usb_stor_blocking_completion
,
NULL
);
usb_stor_blocking_completion
,
NULL
);
/* submit the URB */
/* submit the URB */
...
@@ -1162,7 +1157,7 @@ int usb_stor_Bulk_max_lun(struct us_data *us)
...
@@ -1162,7 +1157,7 @@ int usb_stor_Bulk_max_lun(struct us_data *us)
int
pipe
;
int
pipe
;
/* issue the command -- use usb_control_msg() because
/* issue the command -- use usb_control_msg() because
*
the state machine is not yet alive
*/
*
this is not a scsi queued-command
*/
pipe
=
usb_rcvctrlpipe
(
us
->
pusb_dev
,
0
);
pipe
=
usb_rcvctrlpipe
(
us
->
pusb_dev
,
0
);
result
=
usb_control_msg
(
us
->
pusb_dev
,
pipe
,
result
=
usb_control_msg
(
us
->
pusb_dev
,
pipe
,
US_BULK_GET_MAX_LUN
,
US_BULK_GET_MAX_LUN
,
...
@@ -1181,8 +1176,8 @@ int usb_stor_Bulk_max_lun(struct us_data *us)
...
@@ -1181,8 +1176,8 @@ int usb_stor_Bulk_max_lun(struct us_data *us)
if
(
result
==
-
EPIPE
)
{
if
(
result
==
-
EPIPE
)
{
US_DEBUGP
(
"clearing endpoint halt for pipe 0x%x
\n
"
,
pipe
);
US_DEBUGP
(
"clearing endpoint halt for pipe 0x%x
\n
"
,
pipe
);
/* Use usb_clear_halt() because th
e state machine
/* Use usb_clear_halt() because th
is is not a
*
is not yet alive
*/
*
scsi queued-command
*/
usb_clear_halt
(
us
->
pusb_dev
,
pipe
);
usb_clear_halt
(
us
->
pusb_dev
,
pipe
);
}
}
...
@@ -1356,27 +1351,6 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
...
@@ -1356,27 +1351,6 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
* Reset routines
* Reset routines
***********************************************************************/
***********************************************************************/
struct
us_timeout
{
struct
us_data
*
us
;
spinlock_t
timer_lock
;
};
/* The timeout event handler
*/
static
void
usb_stor_timeout_handler
(
unsigned
long
to__
)
{
struct
us_timeout
*
to
=
(
struct
us_timeout
*
)
to__
;
struct
us_data
*
us
=
to
->
us
;
US_DEBUGP
(
"Timeout occurred
\n
"
);
/* abort the current request */
usb_stor_abort_transport
(
us
);
/* let the reset routine know we have finished */
spin_unlock
(
&
to
->
timer_lock
);
}
/* This is the common part of the device reset code.
/* This is the common part of the device reset code.
*
*
* It's handy that every transport mechanism uses the control endpoint for
* It's handy that every transport mechanism uses the control endpoint for
...
@@ -1385,28 +1359,20 @@ static void usb_stor_timeout_handler(unsigned long to__)
...
@@ -1385,28 +1359,20 @@ static void usb_stor_timeout_handler(unsigned long to__)
* Basically, we send a reset with a 20-second timeout, so we don't get
* Basically, we send a reset with a 20-second timeout, so we don't get
* jammed attempting to do the reset.
* jammed attempting to do the reset.
*/
*/
void
usb_stor_reset_common
(
struct
us_data
*
us
,
u8
request
,
u8
requesttype
,
static
int
usb_stor_reset_common
(
struct
us_data
*
us
,
u8
request
,
u8
requesttype
,
u16
value
,
u16
index
,
void
*
data
,
u16
size
)
u16
value
,
u16
index
,
void
*
data
,
u16
size
)
{
{
int
result
;
int
result
;
struct
us_timeout
timeout_data
=
{
us
,
SPIN_LOCK_UNLOCKED
};
struct
timer_list
timeout_list
;
/* prepare the timeout handler */
spin_lock
(
&
timeout_data
.
timer_lock
);
init_timer
(
&
timeout_list
);
/* A 20-second timeout may seem rather long, but a LaCie
/* A 20-second timeout may seem rather long, but a LaCie
* StudioDrive USB2 device takes 16+ seconds to get going
* StudioDrive USB2 device takes 16+ seconds to get going
* following a powerup or USB attach event. */
* following a powerup or USB attach event. */
timeout_list
.
expires
=
jiffies
+
20
*
HZ
;
/* Use usb_control_msg() because this is not a queued-command */
timeout_list
.
data
=
(
unsigned
long
)
&
timeout_data
;
result
=
usb_control_msg
(
us
->
pusb_dev
,
usb_sndctrlpipe
(
us
->
pusb_dev
,
0
),
timeout_list
.
function
=
usb_stor_timeout_handler
;
request
,
requesttype
,
value
,
index
,
data
,
size
,
add_timer
(
&
timeout_list
);
20
*
HZ
);
result
=
usb_stor_control_msg
(
us
,
usb_sndctrlpipe
(
us
->
pusb_dev
,
0
),
request
,
requesttype
,
value
,
index
,
data
,
size
);
if
(
result
<
0
)
if
(
result
<
0
)
goto
Done
;
goto
Done
;
...
@@ -1415,41 +1381,30 @@ void usb_stor_reset_common(struct us_data *us, u8 request, u8 requesttype,
...
@@ -1415,41 +1381,30 @@ void usb_stor_reset_common(struct us_data *us, u8 request, u8 requesttype,
schedule_timeout
(
HZ
*
6
);
schedule_timeout
(
HZ
*
6
);
set_current_state
(
TASK_RUNNING
);
set_current_state
(
TASK_RUNNING
);
/* Use usb_clear_halt() because this is not a queued-command */
US_DEBUGP
(
"Soft reset: clearing bulk-in endpoint halt
\n
"
);
US_DEBUGP
(
"Soft reset: clearing bulk-in endpoint halt
\n
"
);
result
=
usb_
stor_clear_halt
(
us
,
result
=
usb_
clear_halt
(
us
->
pusb_dev
,
usb_rcvbulkpipe
(
us
->
pusb_dev
,
us
->
ep_in
));
usb_rcvbulkpipe
(
us
->
pusb_dev
,
us
->
ep_in
));
if
(
result
<
0
)
if
(
result
<
0
)
goto
Done
;
goto
Done
;
US_DEBUGP
(
"Soft reset: clearing bulk-out endpoint halt
\n
"
);
US_DEBUGP
(
"Soft reset: clearing bulk-out endpoint halt
\n
"
);
result
=
usb_
stor_clear_halt
(
us
,
result
=
usb_
clear_halt
(
us
->
pusb_dev
,
usb_sndbulkpipe
(
us
->
pusb_dev
,
us
->
ep_out
));
usb_sndbulkpipe
(
us
->
pusb_dev
,
us
->
ep_out
));
Done:
Done:
/* prevent the timer from coming back to haunt us */
if
(
!
del_timer
(
&
timeout_list
))
{
/* the handler has already started; wait for it to finish */
spin_lock
(
&
timeout_data
.
timer_lock
);
/* change the abort into a timeout */
if
(
result
==
-
ENOENT
)
result
=
-
ETIMEDOUT
;
}
/* return a result code based on the result of the control message */
/* return a result code based on the result of the control message */
if
(
result
>=
0
)
if
(
result
<
0
)
{
US_DEBUGP
(
"Soft reset done
\n
"
);
else
US_DEBUGP
(
"Soft reset failed: %d
\n
"
,
result
);
US_DEBUGP
(
"Soft reset failed: %d
\n
"
,
result
);
if
(
result
==
-
ETIMEDOUT
)
us
->
srb
->
result
=
DID_TIME_OUT
<<
16
;
else
if
(
result
==
-
ENOENT
)
us
->
srb
->
result
=
DID_ABORT
<<
16
;
else
if
(
result
<
0
)
us
->
srb
->
result
=
DID_ERROR
<<
16
;
us
->
srb
->
result
=
DID_ERROR
<<
16
;
else
result
=
FAILED
;
}
else
{
US_DEBUGP
(
"Soft reset done
\n
"
);
us
->
srb
->
result
=
GOOD
<<
1
;
us
->
srb
->
result
=
GOOD
<<
1
;
result
=
SUCCESS
;
}
return
result
;
}
}
/* This issues a CB[I] Reset to the device in question
/* This issues a CB[I] Reset to the device in question
...
@@ -1463,10 +1418,9 @@ int usb_stor_CB_reset(struct us_data *us)
...
@@ -1463,10 +1418,9 @@ int usb_stor_CB_reset(struct us_data *us)
memset
(
cmd
,
0xFF
,
sizeof
(
cmd
));
memset
(
cmd
,
0xFF
,
sizeof
(
cmd
));
cmd
[
0
]
=
SEND_DIAGNOSTIC
;
cmd
[
0
]
=
SEND_DIAGNOSTIC
;
cmd
[
1
]
=
4
;
cmd
[
1
]
=
4
;
usb_stor_reset_common
(
us
,
US_CBI_ADSC
,
return
usb_stor_reset_common
(
us
,
US_CBI_ADSC
,
USB_TYPE_CLASS
|
USB_RECIP_INTERFACE
,
USB_TYPE_CLASS
|
USB_RECIP_INTERFACE
,
0
,
us
->
ifnum
,
cmd
,
sizeof
(
cmd
));
0
,
us
->
ifnum
,
cmd
,
sizeof
(
cmd
));
return
(
us
->
srb
->
result
==
GOOD
<<
1
?
SUCCESS
:
FAILED
);
}
}
/* This issues a Bulk-only Reset to the device in question, including
/* This issues a Bulk-only Reset to the device in question, including
...
@@ -1476,8 +1430,7 @@ int usb_stor_Bulk_reset(struct us_data *us)
...
@@ -1476,8 +1430,7 @@ int usb_stor_Bulk_reset(struct us_data *us)
{
{
US_DEBUGP
(
"Bulk reset requested
\n
"
);
US_DEBUGP
(
"Bulk reset requested
\n
"
);
usb_stor_reset_common
(
us
,
US_BULK_RESET_REQUEST
,
return
usb_stor_reset_common
(
us
,
US_BULK_RESET_REQUEST
,
USB_TYPE_CLASS
|
USB_RECIP_INTERFACE
,
USB_TYPE_CLASS
|
USB_RECIP_INTERFACE
,
0
,
us
->
ifnum
,
NULL
,
0
);
0
,
us
->
ifnum
,
NULL
,
0
);
return
(
us
->
srb
->
result
==
GOOD
<<
1
?
SUCCESS
:
FAILED
);
}
}
drivers/usb/storage/usb.c
View file @
9cfc20f1
...
@@ -361,65 +361,42 @@ static int usb_stor_control_thread(void * __us)
...
@@ -361,65 +361,42 @@ static int usb_stor_control_thread(void * __us)
BUG_ON
(
action
!=
US_ACT_COMMAND
);
BUG_ON
(
action
!=
US_ACT_COMMAND
);
/* lock the device pointers */
down
(
&
(
us
->
dev_semaphore
));
/* reject the command if the direction indicator
/* reject the command if the direction indicator
* is UNKNOWN
* is UNKNOWN
*/
*/
if
(
us
->
srb
->
sc_data_direction
==
SCSI_DATA_UNKNOWN
)
{
if
(
us
->
srb
->
sc_data_direction
==
SCSI_DATA_UNKNOWN
)
{
US_DEBUGP
(
"UNKNOWN data direction
\n
"
);
US_DEBUGP
(
"UNKNOWN data direction
\n
"
);
us
->
srb
->
result
=
DID_ERROR
<<
16
;
us
->
srb
->
result
=
DID_ERROR
<<
16
;
scsi_lock
(
host
);
us
->
srb
->
scsi_done
(
us
->
srb
);
us
->
srb
=
NULL
;
scsi_unlock
(
host
);
continue
;
}
}
/* reject if target != 0 or if LUN is higher than
/* reject if target != 0 or if LUN is higher than
* the maximum known LUN
* the maximum known LUN
*/
*/
if
(
us
->
srb
->
target
&&
else
if
(
us
->
srb
->
target
&&
!
(
us
->
flags
&
US_FL_SCM_MULT_TARG
))
{
!
(
us
->
flags
&
US_FL_SCM_MULT_TARG
))
{
US_DEBUGP
(
"Bad target number (%d/%d)
\n
"
,
US_DEBUGP
(
"Bad target number (%d/%d)
\n
"
,
us
->
srb
->
target
,
us
->
srb
->
lun
);
us
->
srb
->
target
,
us
->
srb
->
lun
);
us
->
srb
->
result
=
DID_BAD_TARGET
<<
16
;
us
->
srb
->
result
=
DID_BAD_TARGET
<<
16
;
scsi_lock
(
host
);
us
->
srb
->
scsi_done
(
us
->
srb
);
us
->
srb
=
NULL
;
scsi_unlock
(
host
);
continue
;
}
}
if
(
us
->
srb
->
lun
>
us
->
max_lun
)
{
else
if
(
us
->
srb
->
lun
>
us
->
max_lun
)
{
US_DEBUGP
(
"Bad LUN (%d/%d)
\n
"
,
US_DEBUGP
(
"Bad LUN (%d/%d)
\n
"
,
us
->
srb
->
target
,
us
->
srb
->
lun
);
us
->
srb
->
target
,
us
->
srb
->
lun
);
us
->
srb
->
result
=
DID_BAD_TARGET
<<
16
;
us
->
srb
->
result
=
DID_BAD_TARGET
<<
16
;
scsi_lock
(
host
);
us
->
srb
->
scsi_done
(
us
->
srb
);
us
->
srb
=
NULL
;
scsi_unlock
(
host
);
continue
;
}
}
/* handle those devices which can't do a START_STOP */
/* handle those devices which can't do a START_STOP */
if
((
us
->
srb
->
cmnd
[
0
]
==
START_STOP
)
&&
else
if
((
us
->
srb
->
cmnd
[
0
]
==
START_STOP
)
&&
(
us
->
flags
&
US_FL_START_STOP
))
{
(
us
->
flags
&
US_FL_START_STOP
))
{
US_DEBUGP
(
"Skipping START_STOP command
\n
"
);
US_DEBUGP
(
"Skipping START_STOP command
\n
"
);
us
->
srb
->
result
=
GOOD
<<
1
;
us
->
srb
->
result
=
GOOD
<<
1
;
scsi_lock
(
host
);
us
->
srb
->
scsi_done
(
us
->
srb
);
us
->
srb
=
NULL
;
scsi_unlock
(
host
);
continue
;
}
}
/* lock the device pointers */
down
(
&
(
us
->
dev_semaphore
));
/* our device has gone - pretend not ready */
/* our device has gone - pretend not ready */
if
(
!
test_bit
(
DEV_ATTACHED
,
&
us
->
bitflags
))
{
else
if
(
!
test_bit
(
DEV_ATTACHED
,
&
us
->
bitflags
))
{
US_DEBUGP
(
"Request is for removed device
\n
"
);
US_DEBUGP
(
"Request is for removed device
\n
"
);
/* For REQUEST_SENSE, it's the data. But
/* For REQUEST_SENSE, it's the data. But
* for anything else, it should look like
* for anything else, it should look like
...
@@ -443,24 +420,25 @@ static int usb_stor_control_thread(void * __us)
...
@@ -443,24 +420,25 @@ static int usb_stor_control_thread(void * __us)
sizeof
(
usb_stor_sense_notready
));
sizeof
(
usb_stor_sense_notready
));
us
->
srb
->
result
=
CHECK_CONDITION
<<
1
;
us
->
srb
->
result
=
CHECK_CONDITION
<<
1
;
}
}
}
else
{
/* test_bit(DEV_ATTACHED, &us->bitflags) */
}
/* test_bit(DEV_ATTACHED, &us->bitflags) */
/* Handle those devices which need us to fake
/* Handle those devices which need us to fake
* their inquiry data */
* their inquiry data */
if
((
us
->
srb
->
cmnd
[
0
]
==
INQUIRY
)
&&
else
if
((
us
->
srb
->
cmnd
[
0
]
==
INQUIRY
)
&&
(
us
->
flags
&
US_FL_FIX_INQUIRY
))
{
(
us
->
flags
&
US_FL_FIX_INQUIRY
))
{
unsigned
char
data_ptr
[
36
]
=
{
unsigned
char
data_ptr
[
36
]
=
{
0x00
,
0x80
,
0x02
,
0x02
,
0x00
,
0x80
,
0x02
,
0x02
,
0x1F
,
0x00
,
0x00
,
0x00
};
0x1F
,
0x00
,
0x00
,
0x00
};
US_DEBUGP
(
"Faking INQUIRY command
\n
"
);
US_DEBUGP
(
"Faking INQUIRY command
\n
"
);
fill_inquiry_response
(
us
,
data_ptr
,
36
);
fill_inquiry_response
(
us
,
data_ptr
,
36
);
us
->
srb
->
result
=
GOOD
<<
1
;
us
->
srb
->
result
=
GOOD
<<
1
;
}
else
{
}
/* we've got a command, let's do it! */
US_DEBUG
(
usb_stor_show_command
(
us
->
srb
));
/* we've got a command, let's do it! */
us
->
proto_handler
(
us
->
srb
,
us
);
else
{
}
US_DEBUG
(
usb_stor_show_command
(
us
->
srb
));
us
->
proto_handler
(
us
->
srb
,
us
);
}
}
/* unlock the device pointers */
/* unlock the device pointers */
...
@@ -487,54 +465,114 @@ static int usb_stor_control_thread(void * __us)
...
@@ -487,54 +465,114 @@ static int usb_stor_control_thread(void * __us)
return
0
;
return
0
;
}
}
/* Set up the IRQ pipe and handler
/* Set up the URB, the usb_ctrlrequest, and the IRQ pipe and handler.
* ss->dev_semaphore should already be locked.
* Note that this function assumes that all the data in the us_data
* Note that this function assumes that all the data in the us_data
* strucuture is current. This includes the ep_int field, which gives us
* strucuture is current. This includes the ep_int field, which gives us
* the endpoint for the interrupt.
* the endpoint for the interrupt.
* Returns non-zero on failure, zero on success
* Returns non-zero on failure, zero on success
*/
*/
static
int
usb_stor_allocate_
irq
(
struct
us_data
*
ss
)
static
int
usb_stor_allocate_
urbs
(
struct
us_data
*
ss
)
{
{
unsigned
int
pipe
;
unsigned
int
pipe
;
int
maxp
;
int
maxp
;
int
result
;
int
result
;
US_DEBUGP
(
"Allocating IRQ for CBI transport
\n
"
);
/* allocate the URB we're going to use */
US_DEBUGP
(
"Allocating URB
\n
"
);
/* lock access to the data structure */
ss
->
current_urb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
down
(
&
(
ss
->
irq_urb_sem
));
if
(
!
ss
->
current_urb
)
{
US_DEBUGP
(
"allocation failed
\n
"
);
/* allocate the URB */
ss
->
irq_urb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
if
(
!
ss
->
irq_urb
)
{
up
(
&
(
ss
->
irq_urb_sem
));
US_DEBUGP
(
"couldn't allocate interrupt URB"
);
return
1
;
return
1
;
}
}
/* calculate the pipe and max packet size */
/* allocate the usb_ctrlrequest for control packets */
pipe
=
usb_rcvintpipe
(
ss
->
pusb_dev
,
ss
->
ep_int
->
bEndpointAddress
&
US_DEBUGP
(
"Allocating usb_ctrlrequest
\n
"
);
USB_ENDPOINT_NUMBER_MASK
);
ss
->
dr
=
kmalloc
(
sizeof
(
struct
usb_ctrlrequest
),
GFP_NOIO
);
maxp
=
usb_maxpacket
(
ss
->
pusb_dev
,
pipe
,
usb_pipeout
(
pipe
));
if
(
!
ss
->
dr
)
{
if
(
maxp
>
sizeof
(
ss
->
irqbuf
))
US_DEBUGP
(
"allocation failed
\n
"
);
maxp
=
sizeof
(
ss
->
irqbuf
);
/* fill in the URB with our data */
FILL_INT_URB
(
ss
->
irq_urb
,
ss
->
pusb_dev
,
pipe
,
ss
->
irqbuf
,
maxp
,
usb_stor_CBI_irq
,
ss
,
ss
->
ep_int
->
bInterval
);
/* submit the URB for processing */
result
=
usb_submit_urb
(
ss
->
irq_urb
,
GFP_KERNEL
);
US_DEBUGP
(
"usb_submit_urb() returns %d
\n
"
,
result
);
if
(
result
)
{
usb_free_urb
(
ss
->
irq_urb
);
up
(
&
(
ss
->
irq_urb_sem
));
return
2
;
return
2
;
}
}
/* unlock the data structure and return success */
/* allocate the IRQ URB, if it is needed */
if
(
ss
->
protocol
==
US_PR_CBI
)
{
US_DEBUGP
(
"Allocating IRQ for CBI transport
\n
"
);
/* lock access to the data structure */
down
(
&
(
ss
->
irq_urb_sem
));
/* allocate the URB */
ss
->
irq_urb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
if
(
!
ss
->
irq_urb
)
{
up
(
&
(
ss
->
irq_urb_sem
));
US_DEBUGP
(
"couldn't allocate interrupt URB"
);
return
3
;
}
/* calculate the pipe and max packet size */
pipe
=
usb_rcvintpipe
(
ss
->
pusb_dev
,
ss
->
ep_int
->
bEndpointAddress
&
USB_ENDPOINT_NUMBER_MASK
);
maxp
=
usb_maxpacket
(
ss
->
pusb_dev
,
pipe
,
usb_pipeout
(
pipe
));
if
(
maxp
>
sizeof
(
ss
->
irqbuf
))
maxp
=
sizeof
(
ss
->
irqbuf
);
/* fill in the URB with our data */
FILL_INT_URB
(
ss
->
irq_urb
,
ss
->
pusb_dev
,
pipe
,
ss
->
irqbuf
,
maxp
,
usb_stor_CBI_irq
,
ss
,
ss
->
ep_int
->
bInterval
);
/* submit the URB for processing */
result
=
usb_submit_urb
(
ss
->
irq_urb
,
GFP_KERNEL
);
US_DEBUGP
(
"usb_submit_urb() returns %d
\n
"
,
result
);
if
(
result
)
{
up
(
&
(
ss
->
irq_urb_sem
));
return
4
;
}
/* unlock the data structure */
up
(
&
(
ss
->
irq_urb_sem
));
}
/* ss->protocol == US_PR_CBI */
return
0
;
/* success */
}
/* Deallocate the URB, the usb_ctrlrequest, and the IRQ pipe.
* ss->dev_semaphore must already be locked.
*/
static
void
usb_stor_deallocate_urbs
(
struct
us_data
*
ss
)
{
int
result
;
/* release the IRQ, if we have one */
down
(
&
(
ss
->
irq_urb_sem
));
if
(
ss
->
irq_urb
)
{
US_DEBUGP
(
"-- releasing irq URB
\n
"
);
result
=
usb_unlink_urb
(
ss
->
irq_urb
);
US_DEBUGP
(
"-- usb_unlink_urb() returned %d
\n
"
,
result
);
usb_free_urb
(
ss
->
irq_urb
);
ss
->
irq_urb
=
NULL
;
}
up
(
&
(
ss
->
irq_urb_sem
));
up
(
&
(
ss
->
irq_urb_sem
));
return
0
;
/* free the usb_ctrlrequest buffer */
if
(
ss
->
dr
)
{
kfree
(
ss
->
dr
);
ss
->
dr
=
NULL
;
}
/* free up the main URB for this device */
if
(
ss
->
current_urb
)
{
US_DEBUGP
(
"-- releasing main URB
\n
"
);
result
=
usb_unlink_urb
(
ss
->
current_urb
);
US_DEBUGP
(
"-- usb_unlink_urb() returned %d
\n
"
,
result
);
usb_free_urb
(
ss
->
current_urb
);
ss
->
current_urb
=
NULL
;
}
/* mark the device as gone */
clear_bit
(
DEV_ATTACHED
,
&
ss
->
bitflags
);
usb_put_dev
(
ss
->
pusb_dev
);
ss
->
pusb_dev
=
NULL
;
}
}
/* Probe to see if a new device is actually a SCSI device */
/* Probe to see if a new device is actually a SCSI device */
...
@@ -712,13 +750,8 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
...
@@ -712,13 +750,8 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
USB_ENDPOINT_NUMBER_MASK
;
USB_ENDPOINT_NUMBER_MASK
;
ss
->
ep_int
=
ep_int
;
ss
->
ep_int
=
ep_int
;
/* allocate an IRQ callback if one is needed */
/* allocate the URB, the usb_ctrlrequest, and the IRQ URB */
if
((
ss
->
protocol
==
US_PR_CBI
)
&&
usb_stor_allocate_irq
(
ss
))
if
(
usb_stor_allocate_urbs
(
ss
))
goto
BadDevice
;
/* allocate the URB we're going to use */
ss
->
current_urb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
if
(
!
ss
->
current_urb
)
goto
BadDevice
;
goto
BadDevice
;
/* Re-Initialize the device if it needs it */
/* Re-Initialize the device if it needs it */
...
@@ -741,11 +774,6 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
...
@@ -741,11 +774,6 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
memset
(
ss
,
0
,
sizeof
(
struct
us_data
));
memset
(
ss
,
0
,
sizeof
(
struct
us_data
));
new_device
=
1
;
new_device
=
1
;
/* allocate the URB we're going to use */
ss
->
current_urb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
if
(
!
ss
->
current_urb
)
goto
BadDevice
;
/* Initialize the mutexes only when the struct is new */
/* Initialize the mutexes only when the struct is new */
init_completion
(
&
(
ss
->
notify
));
init_completion
(
&
(
ss
->
notify
));
init_MUTEX_LOCKED
(
&
(
ss
->
ip_waitq
));
init_MUTEX_LOCKED
(
&
(
ss
->
ip_waitq
));
...
@@ -943,8 +971,8 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
...
@@ -943,8 +971,8 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
}
}
US_DEBUGP
(
"Protocol: %s
\n
"
,
ss
->
protocol_name
);
US_DEBUGP
(
"Protocol: %s
\n
"
,
ss
->
protocol_name
);
/* allocate
an IRQ callback if one is needed
*/
/* allocate
the URB, the usb_ctrlrequest, and the IRQ URB
*/
if
(
(
ss
->
protocol
==
US_PR_CBI
)
&&
usb_stor_allocate_irq
(
ss
))
if
(
usb_stor_allocate_urbs
(
ss
))
goto
BadDevice
;
goto
BadDevice
;
/*
/*
...
@@ -1020,26 +1048,11 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
...
@@ -1020,26 +1048,11 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
/* we come here if there are any problems */
/* we come here if there are any problems */
BadDevice:
BadDevice:
US_DEBUGP
(
"storage_probe() failed
\n
"
);
US_DEBUGP
(
"storage_probe() failed
\n
"
);
down
(
&
ss
->
irq_urb_sem
);
usb_stor_deallocate_urbs
(
ss
);
if
(
ss
->
irq_urb
)
{
usb_unlink_urb
(
ss
->
irq_urb
);
usb_free_urb
(
ss
->
irq_urb
);
ss
->
irq_urb
=
NULL
;
}
up
(
&
ss
->
irq_urb_sem
);
if
(
ss
->
current_urb
)
{
usb_unlink_urb
(
ss
->
current_urb
);
usb_free_urb
(
ss
->
current_urb
);
ss
->
current_urb
=
NULL
;
}
clear_bit
(
DEV_ATTACHED
,
&
ss
->
bitflags
);
ss
->
pusb_dev
=
NULL
;
if
(
new_device
)
if
(
new_device
)
kfree
(
ss
);
kfree
(
ss
);
else
else
up
(
&
ss
->
dev_semaphore
);
up
(
&
ss
->
dev_semaphore
);
usb_put_dev
(
dev
);
return
NULL
;
return
NULL
;
}
}
...
@@ -1047,7 +1060,6 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
...
@@ -1047,7 +1060,6 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum,
static
void
storage_disconnect
(
struct
usb_device
*
dev
,
void
*
ptr
)
static
void
storage_disconnect
(
struct
usb_device
*
dev
,
void
*
ptr
)
{
{
struct
us_data
*
ss
=
ptr
;
struct
us_data
*
ss
=
ptr
;
int
result
;
US_DEBUGP
(
"storage_disconnect() called
\n
"
);
US_DEBUGP
(
"storage_disconnect() called
\n
"
);
...
@@ -1057,33 +1069,8 @@ static void storage_disconnect(struct usb_device *dev, void *ptr)
...
@@ -1057,33 +1069,8 @@ static void storage_disconnect(struct usb_device *dev, void *ptr)
return
;
return
;
}
}
/* lock access to the device data structure */
down
(
&
(
ss
->
dev_semaphore
));
down
(
&
(
ss
->
dev_semaphore
));
usb_stor_deallocate_urbs
(
ss
);
/* release the IRQ, if we have one */
down
(
&
(
ss
->
irq_urb_sem
));
if
(
ss
->
irq_urb
)
{
US_DEBUGP
(
"-- releasing irq URB
\n
"
);
result
=
usb_unlink_urb
(
ss
->
irq_urb
);
US_DEBUGP
(
"-- usb_unlink_urb() returned %d
\n
"
,
result
);
usb_free_urb
(
ss
->
irq_urb
);
ss
->
irq_urb
=
NULL
;
}
up
(
&
(
ss
->
irq_urb_sem
));
/* free up the main URB for this device */
US_DEBUGP
(
"-- releasing main URB
\n
"
);
result
=
usb_unlink_urb
(
ss
->
current_urb
);
US_DEBUGP
(
"-- usb_unlink_urb() returned %d
\n
"
,
result
);
usb_free_urb
(
ss
->
current_urb
);
ss
->
current_urb
=
NULL
;
/* mark the device as gone */
usb_put_dev
(
ss
->
pusb_dev
);
ss
->
pusb_dev
=
NULL
;
clear_bit
(
DEV_ATTACHED
,
&
ss
->
bitflags
);
/* unlock access to the device data structure */
up
(
&
(
ss
->
dev_semaphore
));
up
(
&
(
ss
->
dev_semaphore
));
}
}
...
...
drivers/usb/storage/usb.h
View file @
9cfc20f1
...
@@ -185,6 +185,7 @@ struct us_data {
...
@@ -185,6 +185,7 @@ struct us_data {
/* control and bulk communications data */
/* control and bulk communications data */
struct
semaphore
current_urb_sem
;
/* to protect irq_urb */
struct
semaphore
current_urb_sem
;
/* to protect irq_urb */
struct
urb
*
current_urb
;
/* non-int USB requests */
struct
urb
*
current_urb
;
/* non-int USB requests */
struct
usb_ctrlrequest
*
dr
;
/* control requests */
/* the semaphore for sleeping the control thread */
/* the semaphore for sleeping the control thread */
struct
semaphore
sema
;
/* to sleep thread on */
struct
semaphore
sema
;
/* to sleep thread on */
...
...
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