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
e1f015ee
Commit
e1f015ee
authored
Jun 10, 2003
by
Greg Kroah-Hartman
Browse files
Options
Browse Files
Download
Plain Diff
Merge kroah.com:/home/greg/linux/BK/bleed-2.5
into kroah.com:/home/greg/linux/BK/gregkh-2.5
parents
201be7ab
b75f41cf
Changes
16
Show whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
648 additions
and
516 deletions
+648
-516
drivers/usb/core/devio.c
drivers/usb/core/devio.c
+3
-1
drivers/usb/core/hub.c
drivers/usb/core/hub.c
+126
-87
drivers/usb/core/hub.h
drivers/usb/core/hub.h
+6
-1
drivers/usb/gadget/net2280.c
drivers/usb/gadget/net2280.c
+21
-9
drivers/usb/host/ohci-q.c
drivers/usb/host/ohci-q.c
+2
-6
drivers/usb/image/hpusbscsi.c
drivers/usb/image/hpusbscsi.c
+1
-1
drivers/usb/media/vicam.c
drivers/usb/media/vicam.c
+53
-4
drivers/usb/net/catc.c
drivers/usb/net/catc.c
+4
-2
drivers/usb/net/kaweth.c
drivers/usb/net/kaweth.c
+4
-2
drivers/usb/net/pegasus.c
drivers/usb/net/pegasus.c
+78
-28
drivers/usb/net/pegasus.h
drivers/usb/net/pegasus.h
+4
-1
drivers/usb/net/rtl8150.c
drivers/usb/net/rtl8150.c
+4
-2
drivers/usb/storage/transport.c
drivers/usb/storage/transport.c
+32
-2
drivers/usb/storage/transport.h
drivers/usb/storage/transport.h
+4
-2
drivers/usb/storage/usb.c
drivers/usb/storage/usb.c
+304
-363
drivers/usb/storage/usb.h
drivers/usb/storage/usb.h
+2
-5
No files found.
drivers/usb/core/devio.c
View file @
e1f015ee
...
@@ -578,7 +578,9 @@ static int proc_control(struct dev_state *ps, void *arg)
...
@@ -578,7 +578,9 @@ static int proc_control(struct dev_state *ps, void *arg)
}
}
free_page
((
unsigned
long
)
tbuf
);
free_page
((
unsigned
long
)
tbuf
);
if
(
i
<
0
)
{
if
(
i
<
0
)
{
printk
(
KERN_DEBUG
"usbfs: USBDEVFS_CONTROL failed dev %d rqt %u rq %u len %u ret %d
\n
"
,
printk
(
KERN_DEBUG
"usbfs: USBDEVFS_CONTROL failed "
"cmd %s dev %d rqt %u rq %u len %u ret %d
\n
"
,
current
->
comm
,
dev
->
devnum
,
ctrl
.
bRequestType
,
ctrl
.
bRequest
,
ctrl
.
wLength
,
i
);
dev
->
devnum
,
ctrl
.
bRequestType
,
ctrl
.
bRequest
,
ctrl
.
wLength
,
i
);
}
}
return
i
;
return
i
;
...
...
drivers/usb/core/hub.c
View file @
e1f015ee
...
@@ -64,17 +64,17 @@ static inline struct device *hubdev (struct usb_device *dev)
...
@@ -64,17 +64,17 @@ static inline struct device *hubdev (struct usb_device *dev)
}
}
/* USB 2.0 spec Section 11.24.4.5 */
/* USB 2.0 spec Section 11.24.4.5 */
static
int
usb_
get_hub_descriptor
(
struct
usb_device
*
dev
,
void
*
data
,
int
size
)
static
int
get_hub_descriptor
(
struct
usb_device
*
dev
,
void
*
data
,
int
size
)
{
{
return
usb_control_msg
(
dev
,
usb_rcvctrlpipe
(
dev
,
0
),
return
usb_control_msg
(
dev
,
usb_rcvctrlpipe
(
dev
,
0
),
USB_REQ_GET_DESCRIPTOR
,
USB_DIR_IN
|
USB_RT_HUB
,
USB_REQ_GET_DESCRIPTOR
,
USB_DIR_IN
|
USB_RT_HUB
,
USB_DT_HUB
<<
8
,
0
,
data
,
size
,
HZ
);
USB_DT_HUB
<<
8
,
0
,
data
,
size
,
HZ
*
USB_CTRL_GET_TIMEOUT
);
}
}
/*
/*
* USB 2.0 spec Section 11.24.2.1
* USB 2.0 spec Section 11.24.2.1
*/
*/
static
int
usb_
clear_hub_feature
(
struct
usb_device
*
dev
,
int
feature
)
static
int
clear_hub_feature
(
struct
usb_device
*
dev
,
int
feature
)
{
{
return
usb_control_msg
(
dev
,
usb_sndctrlpipe
(
dev
,
0
),
return
usb_control_msg
(
dev
,
usb_sndctrlpipe
(
dev
,
0
),
USB_REQ_CLEAR_FEATURE
,
USB_RT_HUB
,
feature
,
0
,
NULL
,
0
,
HZ
);
USB_REQ_CLEAR_FEATURE
,
USB_RT_HUB
,
feature
,
0
,
NULL
,
0
,
HZ
);
...
@@ -84,7 +84,7 @@ static int usb_clear_hub_feature(struct usb_device *dev, int feature)
...
@@ -84,7 +84,7 @@ static int usb_clear_hub_feature(struct usb_device *dev, int feature)
* USB 2.0 spec Section 11.24.2.2
* USB 2.0 spec Section 11.24.2.2
* BUG: doesn't handle port indicator selector in high byte of wIndex
* BUG: doesn't handle port indicator selector in high byte of wIndex
*/
*/
static
int
usb_
clear_port_feature
(
struct
usb_device
*
dev
,
int
port
,
int
feature
)
static
int
clear_port_feature
(
struct
usb_device
*
dev
,
int
port
,
int
feature
)
{
{
return
usb_control_msg
(
dev
,
usb_sndctrlpipe
(
dev
,
0
),
return
usb_control_msg
(
dev
,
usb_sndctrlpipe
(
dev
,
0
),
USB_REQ_CLEAR_FEATURE
,
USB_RT_PORT
,
feature
,
port
,
NULL
,
0
,
HZ
);
USB_REQ_CLEAR_FEATURE
,
USB_RT_PORT
,
feature
,
port
,
NULL
,
0
,
HZ
);
...
@@ -94,7 +94,7 @@ static int usb_clear_port_feature(struct usb_device *dev, int port, int feature)
...
@@ -94,7 +94,7 @@ static int usb_clear_port_feature(struct usb_device *dev, int port, int feature)
* USB 2.0 spec Section 11.24.2.13
* USB 2.0 spec Section 11.24.2.13
* BUG: doesn't handle port indicator selector in high byte of wIndex
* BUG: doesn't handle port indicator selector in high byte of wIndex
*/
*/
static
int
usb_
set_port_feature
(
struct
usb_device
*
dev
,
int
port
,
int
feature
)
static
int
set_port_feature
(
struct
usb_device
*
dev
,
int
port
,
int
feature
)
{
{
return
usb_control_msg
(
dev
,
usb_sndctrlpipe
(
dev
,
0
),
return
usb_control_msg
(
dev
,
usb_sndctrlpipe
(
dev
,
0
),
USB_REQ_SET_FEATURE
,
USB_RT_PORT
,
feature
,
port
,
NULL
,
0
,
HZ
);
USB_REQ_SET_FEATURE
,
USB_RT_PORT
,
feature
,
port
,
NULL
,
0
,
HZ
);
...
@@ -103,21 +103,23 @@ static int usb_set_port_feature(struct usb_device *dev, int port, int feature)
...
@@ -103,21 +103,23 @@ static int usb_set_port_feature(struct usb_device *dev, int port, int feature)
/*
/*
* USB 2.0 spec Section 11.24.2.6
* USB 2.0 spec Section 11.24.2.6
*/
*/
static
int
usb_get_hub_status
(
struct
usb_device
*
dev
,
void
*
data
)
static
int
get_hub_status
(
struct
usb_device
*
dev
,
struct
usb_hub_status
*
data
)
{
{
return
usb_control_msg
(
dev
,
usb_rcvctrlpipe
(
dev
,
0
),
return
usb_control_msg
(
dev
,
usb_rcvctrlpipe
(
dev
,
0
),
USB_REQ_GET_STATUS
,
USB_DIR_IN
|
USB_RT_HUB
,
0
,
0
,
USB_REQ_GET_STATUS
,
USB_DIR_IN
|
USB_RT_HUB
,
0
,
0
,
data
,
sizeof
(
struct
usb_hub_status
),
HZ
);
data
,
sizeof
(
*
data
),
HZ
*
USB_CTRL_GET_TIMEOUT
);
}
}
/*
/*
* USB 2.0 spec Section 11.24.2.7
* USB 2.0 spec Section 11.24.2.7
*/
*/
static
int
usb_get_port_status
(
struct
usb_device
*
dev
,
int
port
,
void
*
data
)
static
int
get_port_status
(
struct
usb_device
*
dev
,
int
port
,
struct
usb_port_status
*
data
)
{
{
return
usb_control_msg
(
dev
,
usb_rcvctrlpipe
(
dev
,
0
),
return
usb_control_msg
(
dev
,
usb_rcvctrlpipe
(
dev
,
0
),
USB_REQ_GET_STATUS
,
USB_DIR_IN
|
USB_RT_PORT
,
0
,
port
,
USB_REQ_GET_STATUS
,
USB_DIR_IN
|
USB_RT_PORT
,
0
,
port
,
data
,
sizeof
(
struct
usb_hub_status
),
HZ
);
data
,
sizeof
(
*
data
),
HZ
*
USB_CTRL_GET_TIMEOUT
);
}
}
/* completion function, fires on port status changes and various faults */
/* completion function, fires on port status changes and various faults */
...
@@ -256,7 +258,7 @@ void usb_hub_tt_clear_buffer (struct usb_device *dev, int pipe)
...
@@ -256,7 +258,7 @@ void usb_hub_tt_clear_buffer (struct usb_device *dev, int pipe)
spin_unlock_irqrestore
(
&
tt
->
lock
,
flags
);
spin_unlock_irqrestore
(
&
tt
->
lock
,
flags
);
}
}
static
void
usb_
hub_power_on
(
struct
usb_hub
*
hub
)
static
void
hub_power_on
(
struct
usb_hub
*
hub
)
{
{
struct
usb_device
*
dev
;
struct
usb_device
*
dev
;
int
i
;
int
i
;
...
@@ -266,22 +268,55 @@ static void usb_hub_power_on(struct usb_hub *hub)
...
@@ -266,22 +268,55 @@ static void usb_hub_power_on(struct usb_hub *hub)
"enabling power on all ports
\n
"
);
"enabling power on all ports
\n
"
);
dev
=
interface_to_usbdev
(
hub
->
intf
);
dev
=
interface_to_usbdev
(
hub
->
intf
);
for
(
i
=
0
;
i
<
hub
->
descriptor
->
bNbrPorts
;
i
++
)
for
(
i
=
0
;
i
<
hub
->
descriptor
->
bNbrPorts
;
i
++
)
usb_
set_port_feature
(
dev
,
i
+
1
,
USB_PORT_FEAT_POWER
);
set_port_feature
(
dev
,
i
+
1
,
USB_PORT_FEAT_POWER
);
/* Wait for power to be enabled */
/* Wait for power to be enabled */
wait_ms
(
hub
->
descriptor
->
bPwrOn2PwrGood
*
2
);
wait_ms
(
hub
->
descriptor
->
bPwrOn2PwrGood
*
2
);
}
}
static
int
usb_hub_configure
(
struct
usb_hub
*
hub
,
static
int
hub_hub_status
(
struct
usb_hub
*
hub
,
u16
*
status
,
u16
*
change
)
{
struct
usb_device
*
dev
=
interface_to_usbdev
(
hub
->
intf
);
int
ret
;
ret
=
get_hub_status
(
dev
,
&
hub
->
status
->
hub
);
if
(
ret
<
0
)
dev_err
(
hubdev
(
dev
),
"%s failed (err = %d)
\n
"
,
__FUNCTION__
,
ret
);
else
{
*
status
=
le16_to_cpu
(
hub
->
status
->
hub
.
wHubStatus
);
*
change
=
le16_to_cpu
(
hub
->
status
->
hub
.
wHubChange
);
ret
=
0
;
}
return
ret
;
}
static
int
hub_configure
(
struct
usb_hub
*
hub
,
struct
usb_endpoint_descriptor
*
endpoint
)
struct
usb_endpoint_descriptor
*
endpoint
)
{
{
struct
usb_device
*
dev
=
interface_to_usbdev
(
hub
->
intf
);
struct
usb_device
*
dev
=
interface_to_usbdev
(
hub
->
intf
);
struct
device
*
hub_dev
;
struct
device
*
hub_dev
;
struct
usb_hub_status
hubstatus
;
u16
hubstatus
,
hubchange
;
unsigned
int
pipe
;
unsigned
int
pipe
;
int
maxp
,
ret
;
int
maxp
,
ret
;
char
*
message
;
char
*
message
;
hub
->
buffer
=
usb_buffer_alloc
(
dev
,
sizeof
(
*
hub
->
buffer
),
GFP_KERNEL
,
&
hub
->
buffer_dma
);
if
(
!
hub
->
buffer
)
{
message
=
"can't allocate hub irq buffer"
;
ret
=
-
ENOMEM
;
goto
fail
;
}
hub
->
status
=
kmalloc
(
sizeof
(
*
hub
->
status
),
GFP_KERNEL
);
if
(
!
hub
->
status
)
{
message
=
"can't kmalloc hub status buffer"
;
ret
=
-
ENOMEM
;
goto
fail
;
}
hub
->
descriptor
=
kmalloc
(
sizeof
(
*
hub
->
descriptor
),
GFP_KERNEL
);
hub
->
descriptor
=
kmalloc
(
sizeof
(
*
hub
->
descriptor
),
GFP_KERNEL
);
if
(
!
hub
->
descriptor
)
{
if
(
!
hub
->
descriptor
)
{
message
=
"can't kmalloc hub descriptor"
;
message
=
"can't kmalloc hub descriptor"
;
...
@@ -293,7 +328,7 @@ static int usb_hub_configure(struct usb_hub *hub,
...
@@ -293,7 +328,7 @@ static int usb_hub_configure(struct usb_hub *hub,
* hub->descriptor can handle USB_MAXCHILDREN ports,
* hub->descriptor can handle USB_MAXCHILDREN ports,
* but the hub can/will return fewer bytes here.
* but the hub can/will return fewer bytes here.
*/
*/
ret
=
usb_
get_hub_descriptor
(
dev
,
hub
->
descriptor
,
ret
=
get_hub_descriptor
(
dev
,
hub
->
descriptor
,
sizeof
(
*
hub
->
descriptor
));
sizeof
(
*
hub
->
descriptor
));
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
message
=
"can't read hub descriptor"
;
message
=
"can't read hub descriptor"
;
...
@@ -396,27 +431,25 @@ static int usb_hub_configure(struct usb_hub *hub,
...
@@ -396,27 +431,25 @@ static int usb_hub_configure(struct usb_hub *hub,
dev_dbg
(
hub_dev
,
"hub controller current requirement: %dmA
\n
"
,
dev_dbg
(
hub_dev
,
"hub controller current requirement: %dmA
\n
"
,
hub
->
descriptor
->
bHubContrCurrent
);
hub
->
descriptor
->
bHubContrCurrent
);
ret
=
usb_get_hub_status
(
dev
,
&
hubstatus
);
ret
=
hub_hub_status
(
hub
,
&
hubstatus
,
&
hubchange
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
message
=
"can't get hub status"
;
message
=
"can't get hub status"
;
goto
fail
;
goto
fail
;
}
}
le16_to_cpus
(
&
hubstatus
.
wHubStatus
);
dev_dbg
(
hub_dev
,
"local power source is %s
\n
"
,
dev_dbg
(
hub_dev
,
"local power source is %s
\n
"
,
(
hubstatus
.
wHubStatus
&
HUB_STATUS_LOCAL_POWER
)
(
hubstatus
&
HUB_STATUS_LOCAL_POWER
)
?
"lost (inactive)"
:
"good"
);
?
"lost (inactive)"
:
"good"
);
dev_dbg
(
hub_dev
,
"%sover-current condition exists
\n
"
,
dev_dbg
(
hub_dev
,
"%sover-current condition exists
\n
"
,
(
hubstatus
.
wHubStatus
&
HUB_STATUS_OVERCURRENT
)
?
""
:
"no "
);
(
hubstatus
&
HUB_STATUS_OVERCURRENT
)
?
""
:
"no "
);
/* Start the interrupt endpoint */
/* Start the interrupt endpoint */
pipe
=
usb_rcvintpipe
(
dev
,
endpoint
->
bEndpointAddress
);
pipe
=
usb_rcvintpipe
(
dev
,
endpoint
->
bEndpointAddress
);
maxp
=
usb_maxpacket
(
dev
,
pipe
,
usb_pipeout
(
pipe
));
maxp
=
usb_maxpacket
(
dev
,
pipe
,
usb_pipeout
(
pipe
));
if
(
maxp
>
sizeof
(
hub
->
buffer
))
if
(
maxp
>
sizeof
(
*
hub
->
buffer
))
maxp
=
sizeof
(
hub
->
buffer
);
maxp
=
sizeof
(
*
hub
->
buffer
);
hub
->
urb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
hub
->
urb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
if
(
!
hub
->
urb
)
{
if
(
!
hub
->
urb
)
{
...
@@ -425,8 +458,10 @@ static int usb_hub_configure(struct usb_hub *hub,
...
@@ -425,8 +458,10 @@ static int usb_hub_configure(struct usb_hub *hub,
goto
fail
;
goto
fail
;
}
}
usb_fill_int_urb
(
hub
->
urb
,
dev
,
pipe
,
hub
->
buffer
,
maxp
,
hub_irq
,
usb_fill_int_urb
(
hub
->
urb
,
dev
,
pipe
,
*
hub
->
buffer
,
maxp
,
hub_irq
,
hub
,
endpoint
->
bInterval
);
hub
,
endpoint
->
bInterval
);
hub
->
urb
->
transfer_dma
=
hub
->
buffer_dma
;
hub
->
urb
->
transfer_flags
|=
URB_NO_DMA_MAP
;
ret
=
usb_submit_urb
(
hub
->
urb
,
GFP_KERNEL
);
ret
=
usb_submit_urb
(
hub
->
urb
,
GFP_KERNEL
);
if
(
ret
)
{
if
(
ret
)
{
message
=
"couldn't submit status urb"
;
message
=
"couldn't submit status urb"
;
...
@@ -436,7 +471,7 @@ static int usb_hub_configure(struct usb_hub *hub,
...
@@ -436,7 +471,7 @@ static int usb_hub_configure(struct usb_hub *hub,
/* Wake up khubd */
/* Wake up khubd */
wake_up
(
&
khubd_wait
);
wake_up
(
&
khubd_wait
);
usb_
hub_power_on
(
hub
);
hub_power_on
(
hub
);
return
0
;
return
0
;
...
@@ -484,6 +519,18 @@ static void hub_disconnect(struct usb_interface *intf)
...
@@ -484,6 +519,18 @@ static void hub_disconnect(struct usb_interface *intf)
hub
->
descriptor
=
NULL
;
hub
->
descriptor
=
NULL
;
}
}
if
(
hub
->
status
)
{
kfree
(
hub
->
status
);
hub
->
status
=
NULL
;
}
if
(
hub
->
buffer
)
{
usb_buffer_free
(
interface_to_usbdev
(
intf
),
sizeof
(
*
hub
->
buffer
),
hub
->
buffer
,
hub
->
buffer_dma
);
hub
->
buffer
=
NULL
;
}
/* Free the memory */
/* Free the memory */
kfree
(
hub
);
kfree
(
hub
);
}
}
...
@@ -550,7 +597,7 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
...
@@ -550,7 +597,7 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
usb_set_intfdata
(
intf
,
hub
);
usb_set_intfdata
(
intf
,
hub
);
if
(
usb_
hub_configure
(
hub
,
endpoint
)
>=
0
)
{
if
(
hub_configure
(
hub
,
endpoint
)
>=
0
)
{
strcpy
(
intf
->
dev
.
name
,
"Hub"
);
strcpy
(
intf
->
dev
.
name
,
"Hub"
);
return
0
;
return
0
;
}
}
...
@@ -594,7 +641,7 @@ hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data)
...
@@ -594,7 +641,7 @@ hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data)
}
}
}
}
static
int
usb_
hub_reset
(
struct
usb_hub
*
hub
)
static
int
hub_reset
(
struct
usb_hub
*
hub
)
{
{
struct
usb_device
*
dev
=
interface_to_usbdev
(
hub
->
intf
);
struct
usb_device
*
dev
=
interface_to_usbdev
(
hub
->
intf
);
int
i
;
int
i
;
...
@@ -618,12 +665,12 @@ static int usb_hub_reset(struct usb_hub *hub)
...
@@ -618,12 +665,12 @@ static int usb_hub_reset(struct usb_hub *hub)
if
(
usb_submit_urb
(
hub
->
urb
,
GFP_KERNEL
))
if
(
usb_submit_urb
(
hub
->
urb
,
GFP_KERNEL
))
return
-
1
;
return
-
1
;
usb_
hub_power_on
(
hub
);
hub_power_on
(
hub
);
return
0
;
return
0
;
}
}
static
void
usb_hub
_disconnect
(
struct
usb_device
*
dev
)
static
void
hub_start
_disconnect
(
struct
usb_device
*
dev
)
{
{
struct
usb_device
*
parent
=
dev
->
parent
;
struct
usb_device
*
parent
=
dev
->
parent
;
int
i
;
int
i
;
...
@@ -641,26 +688,21 @@ static void usb_hub_disconnect(struct usb_device *dev)
...
@@ -641,26 +688,21 @@ static void usb_hub_disconnect(struct usb_device *dev)
err
(
"cannot disconnect hub %s"
,
dev
->
devpath
);
err
(
"cannot disconnect hub %s"
,
dev
->
devpath
);
}
}
static
int
usb_hub_port_status
(
struct
usb_device
*
hub
,
int
port
,
static
int
hub_port_status
(
struct
usb_device
*
dev
,
int
port
,
u16
*
status
,
u16
*
change
)
u16
*
status
,
u16
*
change
)
{
{
struct
usb_
port_status
*
portsts
;
struct
usb_
hub
*
hub
=
usb_get_intfdata
(
dev
->
actconfig
->
interface
)
;
int
ret
=
-
ENOMEM
;
int
ret
;
portsts
=
kmalloc
(
sizeof
(
*
portsts
),
GFP_NOIO
);
ret
=
get_port_status
(
dev
,
port
+
1
,
&
hub
->
status
->
port
);
if
(
portsts
)
{
ret
=
usb_get_port_status
(
hub
,
port
+
1
,
portsts
);
if
(
ret
<
0
)
if
(
ret
<
0
)
dev_err
(
hubdev
(
hub
),
dev_err
(
hubdev
(
dev
),
"%s failed (err = %d)
\n
"
,
__FUNCTION__
,
"%s failed (err = %d)
\n
"
,
__FUNCTION__
,
ret
);
ret
);
else
{
else
{
*
status
=
le16_to_cpu
(
portsts
->
wPortStatus
);
*
status
=
le16_to_cpu
(
hub
->
status
->
port
.
wPortStatus
);
*
change
=
le16_to_cpu
(
portsts
->
wPortChange
);
*
change
=
le16_to_cpu
(
hub
->
status
->
port
.
wPortChange
);
ret
=
0
;
ret
=
0
;
}
}
kfree
(
portsts
);
}
return
ret
;
return
ret
;
}
}
...
@@ -671,7 +713,7 @@ static int usb_hub_port_status(struct usb_device *hub, int port,
...
@@ -671,7 +713,7 @@ static int usb_hub_port_status(struct usb_device *hub, int port,
#define HUB_RESET_TIMEOUT 500
#define HUB_RESET_TIMEOUT 500
/* return: -1 on error, 0 on success, 1 on disconnect. */
/* return: -1 on error, 0 on success, 1 on disconnect. */
static
int
usb_
hub_port_wait_reset
(
struct
usb_device
*
hub
,
int
port
,
static
int
hub_port_wait_reset
(
struct
usb_device
*
hub
,
int
port
,
struct
usb_device
*
dev
,
unsigned
int
delay
)
struct
usb_device
*
dev
,
unsigned
int
delay
)
{
{
int
delay_time
,
ret
;
int
delay_time
,
ret
;
...
@@ -685,7 +727,7 @@ static int usb_hub_port_wait_reset(struct usb_device *hub, int port,
...
@@ -685,7 +727,7 @@ static int usb_hub_port_wait_reset(struct usb_device *hub, int port,
wait_ms
(
delay
);
wait_ms
(
delay
);
/* read and decode port status */
/* read and decode port status */
ret
=
usb_
hub_port_status
(
hub
,
port
,
&
portstatus
,
&
portchange
);
ret
=
hub_port_status
(
hub
,
port
,
&
portstatus
,
&
portchange
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
return
-
1
;
return
-
1
;
}
}
...
@@ -723,19 +765,19 @@ static int usb_hub_port_wait_reset(struct usb_device *hub, int port,
...
@@ -723,19 +765,19 @@ static int usb_hub_port_wait_reset(struct usb_device *hub, int port,
}
}
/* return: -1 on error, 0 on success, 1 on disconnect. */
/* return: -1 on error, 0 on success, 1 on disconnect. */
static
int
usb_
hub_port_reset
(
struct
usb_device
*
hub
,
int
port
,
static
int
hub_port_reset
(
struct
usb_device
*
hub
,
int
port
,
struct
usb_device
*
dev
,
unsigned
int
delay
)
struct
usb_device
*
dev
,
unsigned
int
delay
)
{
{
int
i
,
status
;
int
i
,
status
;
/* Reset the port */
/* Reset the port */
for
(
i
=
0
;
i
<
HUB_RESET_TRIES
;
i
++
)
{
for
(
i
=
0
;
i
<
HUB_RESET_TRIES
;
i
++
)
{
usb_
set_port_feature
(
hub
,
port
+
1
,
USB_PORT_FEAT_RESET
);
set_port_feature
(
hub
,
port
+
1
,
USB_PORT_FEAT_RESET
);
/* return on disconnect or reset */
/* return on disconnect or reset */
status
=
usb_
hub_port_wait_reset
(
hub
,
port
,
dev
,
delay
);
status
=
hub_port_wait_reset
(
hub
,
port
,
dev
,
delay
);
if
(
status
!=
-
1
)
{
if
(
status
!=
-
1
)
{
usb_
clear_port_feature
(
hub
,
clear_port_feature
(
hub
,
port
+
1
,
USB_PORT_FEAT_C_RESET
);
port
+
1
,
USB_PORT_FEAT_C_RESET
);
dev
->
state
=
status
dev
->
state
=
status
?
USB_STATE_NOTATTACHED
?
USB_STATE_NOTATTACHED
...
@@ -756,11 +798,11 @@ static int usb_hub_port_reset(struct usb_device *hub, int port,
...
@@ -756,11 +798,11 @@ static int usb_hub_port_reset(struct usb_device *hub, int port,
return
-
1
;
return
-
1
;
}
}
int
usb_
hub_port_disable
(
struct
usb_device
*
hub
,
int
port
)
int
hub_port_disable
(
struct
usb_device
*
hub
,
int
port
)
{
{
int
ret
;
int
ret
;
ret
=
usb_
clear_port_feature
(
hub
,
port
+
1
,
USB_PORT_FEAT_ENABLE
);
ret
=
clear_port_feature
(
hub
,
port
+
1
,
USB_PORT_FEAT_ENABLE
);
if
(
ret
)
if
(
ret
)
dev_err
(
hubdev
(
hub
),
"cannot disable port %d (err = %d)
\n
"
,
dev_err
(
hubdev
(
hub
),
"cannot disable port %d (err = %d)
\n
"
,
port
+
1
,
ret
);
port
+
1
,
ret
);
...
@@ -787,7 +829,7 @@ int usb_hub_port_disable(struct usb_device *hub, int port)
...
@@ -787,7 +829,7 @@ int usb_hub_port_disable(struct usb_device *hub, int port)
#define HUB_DEBOUNCE_STABLE 4
#define HUB_DEBOUNCE_STABLE 4
/* return: -1 on error, 0 on success, 1 on disconnect. */
/* return: -1 on error, 0 on success, 1 on disconnect. */
static
int
usb_
hub_port_debounce
(
struct
usb_device
*
hub
,
int
port
)
static
int
hub_port_debounce
(
struct
usb_device
*
hub
,
int
port
)
{
{
int
ret
;
int
ret
;
int
delay_time
,
stable_count
;
int
delay_time
,
stable_count
;
...
@@ -799,7 +841,7 @@ static int usb_hub_port_debounce(struct usb_device *hub, int port)
...
@@ -799,7 +841,7 @@ static int usb_hub_port_debounce(struct usb_device *hub, int port)
for
(
delay_time
=
0
;
delay_time
<
HUB_DEBOUNCE_TIMEOUT
;
delay_time
+=
HUB_DEBOUNCE_STEP
)
{
for
(
delay_time
=
0
;
delay_time
<
HUB_DEBOUNCE_TIMEOUT
;
delay_time
+=
HUB_DEBOUNCE_STEP
)
{
wait_ms
(
HUB_DEBOUNCE_STEP
);
wait_ms
(
HUB_DEBOUNCE_STEP
);
ret
=
usb_
hub_port_status
(
hub
,
port
,
&
portstatus
,
&
portchange
);
ret
=
hub_port_status
(
hub
,
port
,
&
portstatus
,
&
portchange
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
-
1
;
return
-
1
;
...
@@ -814,7 +856,7 @@ static int usb_hub_port_debounce(struct usb_device *hub, int port)
...
@@ -814,7 +856,7 @@ static int usb_hub_port_debounce(struct usb_device *hub, int port)
connection
=
portstatus
&
USB_PORT_STAT_CONNECTION
;
connection
=
portstatus
&
USB_PORT_STAT_CONNECTION
;
if
((
portchange
&
USB_PORT_STAT_C_CONNECTION
))
{
if
((
portchange
&
USB_PORT_STAT_C_CONNECTION
))
{
usb_
clear_port_feature
(
hub
,
port
+
1
,
USB_PORT_FEAT_C_CONNECTION
);
clear_port_feature
(
hub
,
port
+
1
,
USB_PORT_FEAT_C_CONNECTION
);
}
}
}
}
...
@@ -826,7 +868,7 @@ static int usb_hub_port_debounce(struct usb_device *hub, int port)
...
@@ -826,7 +868,7 @@ static int usb_hub_port_debounce(struct usb_device *hub, int port)
return
((
portstatus
&
USB_PORT_STAT_CONNECTION
))
?
0
:
1
;
return
((
portstatus
&
USB_PORT_STAT_CONNECTION
))
?
0
:
1
;
}
}
static
void
usb_
hub_port_connect_change
(
struct
usb_hub
*
hubstate
,
int
port
,
static
void
hub_port_connect_change
(
struct
usb_hub
*
hubstate
,
int
port
,
u16
portstatus
,
u16
portchange
)
u16
portstatus
,
u16
portchange
)
{
{
struct
usb_device
*
hub
=
interface_to_usbdev
(
hubstate
->
intf
);
struct
usb_device
*
hub
=
interface_to_usbdev
(
hubstate
->
intf
);
...
@@ -839,7 +881,7 @@ static void usb_hub_port_connect_change(struct usb_hub *hubstate, int port,
...
@@ -839,7 +881,7 @@ static void usb_hub_port_connect_change(struct usb_hub *hubstate, int port,
port
+
1
,
portstatus
,
portchange
,
portspeed
(
portstatus
));
port
+
1
,
portstatus
,
portchange
,
portspeed
(
portstatus
));
/* Clear the connection change status */
/* Clear the connection change status */
usb_
clear_port_feature
(
hub
,
port
+
1
,
USB_PORT_FEAT_C_CONNECTION
);
clear_port_feature
(
hub
,
port
+
1
,
USB_PORT_FEAT_C_CONNECTION
);
/* Disconnect any existing devices under this port */
/* Disconnect any existing devices under this port */
if
(
hub
->
children
[
port
])
if
(
hub
->
children
[
port
])
...
@@ -848,16 +890,16 @@ static void usb_hub_port_connect_change(struct usb_hub *hubstate, int port,
...
@@ -848,16 +890,16 @@ static void usb_hub_port_connect_change(struct usb_hub *hubstate, int port,
/* Return now if nothing is connected */
/* Return now if nothing is connected */
if
(
!
(
portstatus
&
USB_PORT_STAT_CONNECTION
))
{
if
(
!
(
portstatus
&
USB_PORT_STAT_CONNECTION
))
{
if
(
portstatus
&
USB_PORT_STAT_ENABLE
)
if
(
portstatus
&
USB_PORT_STAT_ENABLE
)
usb_
hub_port_disable
(
hub
,
port
);
hub_port_disable
(
hub
,
port
);
return
;
return
;
}
}
if
(
usb_
hub_port_debounce
(
hub
,
port
))
{
if
(
hub_port_debounce
(
hub
,
port
))
{
dev_err
(
&
hubstate
->
intf
->
dev
,
dev_err
(
&
hubstate
->
intf
->
dev
,
"connect-debounce failed, port %d disabled
\n
"
,
"connect-debounce failed, port %d disabled
\n
"
,
port
+
1
);
port
+
1
);
usb_
hub_port_disable
(
hub
,
port
);
hub_port_disable
(
hub
,
port
);
return
;
return
;
}
}
...
@@ -884,7 +926,7 @@ static void usb_hub_port_connect_change(struct usb_hub *hubstate, int port,
...
@@ -884,7 +926,7 @@ static void usb_hub_port_connect_change(struct usb_hub *hubstate, int port,
dev
->
state
=
USB_STATE_POWERED
;
dev
->
state
=
USB_STATE_POWERED
;
/* Reset the device, and detect its speed */
/* Reset the device, and detect its speed */
if
(
usb_
hub_port_reset
(
hub
,
port
,
dev
,
delay
))
{
if
(
hub_port_reset
(
hub
,
port
,
dev
,
delay
))
{
usb_put_dev
(
dev
);
usb_put_dev
(
dev
);
break
;
break
;
}
}
...
@@ -944,18 +986,17 @@ static void usb_hub_port_connect_change(struct usb_hub *hubstate, int port,
...
@@ -944,18 +986,17 @@ static void usb_hub_port_connect_change(struct usb_hub *hubstate, int port,
}
}
hub
->
children
[
port
]
=
NULL
;
hub
->
children
[
port
]
=
NULL
;
usb_
hub_port_disable
(
hub
,
port
);
hub_port_disable
(
hub
,
port
);
done:
done:
up
(
&
usb_address0_sem
);
up
(
&
usb_address0_sem
);
}
}
static
void
usb_
hub_events
(
void
)
static
void
hub_events
(
void
)
{
{
unsigned
long
flags
;
unsigned
long
flags
;
struct
list_head
*
tmp
;
struct
list_head
*
tmp
;
struct
usb_device
*
dev
;
struct
usb_device
*
dev
;
struct
usb_hub
*
hub
;
struct
usb_hub
*
hub
;
struct
usb_hub_status
hubsts
;
u16
hubstatus
;
u16
hubstatus
;
u16
hubchange
;
u16
hubchange
;
u16
portstatus
;
u16
portstatus
;
...
@@ -991,11 +1032,11 @@ static void usb_hub_events(void)
...
@@ -991,11 +1032,11 @@ static void usb_hub_events(void)
dev_dbg
(
&
hub
->
intf
->
dev
,
"resetting for error %d
\n
"
,
dev_dbg
(
&
hub
->
intf
->
dev
,
"resetting for error %d
\n
"
,
hub
->
error
);
hub
->
error
);
if
(
usb_
hub_reset
(
hub
))
{
if
(
hub_reset
(
hub
))
{
dev_dbg
(
&
hub
->
intf
->
dev
,
dev_dbg
(
&
hub
->
intf
->
dev
,
"can't reset; disconnecting
\n
"
);
"can't reset; disconnecting
\n
"
);
up
(
&
hub
->
khubd_sem
);
up
(
&
hub
->
khubd_sem
);
usb_hub
_disconnect
(
dev
);
hub_start
_disconnect
(
dev
);
continue
;
continue
;
}
}
...
@@ -1004,18 +1045,18 @@ static void usb_hub_events(void)
...
@@ -1004,18 +1045,18 @@ static void usb_hub_events(void)
}
}
for
(
i
=
0
;
i
<
hub
->
descriptor
->
bNbrPorts
;
i
++
)
{
for
(
i
=
0
;
i
<
hub
->
descriptor
->
bNbrPorts
;
i
++
)
{
ret
=
usb_
hub_port_status
(
dev
,
i
,
&
portstatus
,
&
portchange
);
ret
=
hub_port_status
(
dev
,
i
,
&
portstatus
,
&
portchange
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
continue
;
continue
;
}
}
if
(
portchange
&
USB_PORT_STAT_C_CONNECTION
)
{
if
(
portchange
&
USB_PORT_STAT_C_CONNECTION
)
{
usb_
hub_port_connect_change
(
hub
,
i
,
portstatus
,
portchange
);
hub_port_connect_change
(
hub
,
i
,
portstatus
,
portchange
);
}
else
if
(
portchange
&
USB_PORT_STAT_C_ENABLE
)
{
}
else
if
(
portchange
&
USB_PORT_STAT_C_ENABLE
)
{
dev_dbg
(
hubdev
(
dev
),
dev_dbg
(
hubdev
(
dev
),
"port %d enable change, status %x
\n
"
,
"port %d enable change, status %x
\n
"
,
i
+
1
,
portstatus
);
i
+
1
,
portstatus
);
usb_
clear_port_feature
(
dev
,
clear_port_feature
(
dev
,
i
+
1
,
USB_PORT_FEAT_C_ENABLE
);
i
+
1
,
USB_PORT_FEAT_C_ENABLE
);
/*
/*
...
@@ -1032,7 +1073,7 @@ static void usb_hub_events(void)
...
@@ -1032,7 +1073,7 @@ static void usb_hub_events(void)
"disabled by hub (EMI?), "
"disabled by hub (EMI?), "
"re-enabling..."
,
"re-enabling..."
,
i
+
1
);
i
+
1
);
usb_
hub_port_connect_change
(
hub
,
hub_port_connect_change
(
hub
,
i
,
portstatus
,
portchange
);
i
,
portstatus
,
portchange
);
}
}
}
}
...
@@ -1041,7 +1082,7 @@ static void usb_hub_events(void)
...
@@ -1041,7 +1082,7 @@ static void usb_hub_events(void)
dev_dbg
(
&
hub
->
intf
->
dev
,
dev_dbg
(
&
hub
->
intf
->
dev
,
"suspend change on port %d
\n
"
,
"suspend change on port %d
\n
"
,
i
+
1
);
i
+
1
);
usb_
clear_port_feature
(
dev
,
clear_port_feature
(
dev
,
i
+
1
,
USB_PORT_FEAT_C_SUSPEND
);
i
+
1
,
USB_PORT_FEAT_C_SUSPEND
);
}
}
...
@@ -1049,35 +1090,33 @@ static void usb_hub_events(void)
...
@@ -1049,35 +1090,33 @@ static void usb_hub_events(void)
dev_err
(
&
hub
->
intf
->
dev
,
dev_err
(
&
hub
->
intf
->
dev
,
"over-current change on port %d
\n
"
,
"over-current change on port %d
\n
"
,
i
+
1
);
i
+
1
);
usb_
clear_port_feature
(
dev
,
clear_port_feature
(
dev
,
i
+
1
,
USB_PORT_FEAT_C_OVER_CURRENT
);
i
+
1
,
USB_PORT_FEAT_C_OVER_CURRENT
);
usb_
hub_power_on
(
hub
);
hub_power_on
(
hub
);
}
}
if
(
portchange
&
USB_PORT_STAT_C_RESET
)
{
if
(
portchange
&
USB_PORT_STAT_C_RESET
)
{
dev_dbg
(
&
hub
->
intf
->
dev
,
dev_dbg
(
&
hub
->
intf
->
dev
,
"reset change on port %d
\n
"
,
"reset change on port %d
\n
"
,
i
+
1
);
i
+
1
);
usb_
clear_port_feature
(
dev
,
clear_port_feature
(
dev
,
i
+
1
,
USB_PORT_FEAT_C_RESET
);
i
+
1
,
USB_PORT_FEAT_C_RESET
);
}
}
}
/* end for i */
}
/* end for i */
/* deal with hub status changes */
/* deal with hub status changes */
if
(
usb_get_hub_status
(
dev
,
&
hubsts
)
<
0
)
if
(
hub_hub_status
(
hub
,
&
hubstatus
,
&
hubchange
)
<
0
)
dev_err
(
&
hub
->
intf
->
dev
,
"get_hub_status failed
\n
"
);
dev_err
(
&
hub
->
intf
->
dev
,
"get_hub_status failed
\n
"
);
else
{
else
{
hubstatus
=
le16_to_cpup
(
&
hubsts
.
wHubStatus
);
hubchange
=
le16_to_cpup
(
&
hubsts
.
wHubChange
);
if
(
hubchange
&
HUB_CHANGE_LOCAL_POWER
)
{
if
(
hubchange
&
HUB_CHANGE_LOCAL_POWER
)
{
dev_dbg
(
&
hub
->
intf
->
dev
,
"power change
\n
"
);
dev_dbg
(
&
hub
->
intf
->
dev
,
"power change
\n
"
);
usb_
clear_hub_feature
(
dev
,
C_HUB_LOCAL_POWER
);
clear_hub_feature
(
dev
,
C_HUB_LOCAL_POWER
);
}
}
if
(
hubchange
&
HUB_CHANGE_OVERCURRENT
)
{
if
(
hubchange
&
HUB_CHANGE_OVERCURRENT
)
{
dev_dbg
(
&
hub
->
intf
->
dev
,
"overcurrent change
\n
"
);
dev_dbg
(
&
hub
->
intf
->
dev
,
"overcurrent change
\n
"
);
wait_ms
(
500
);
/* Cool down */
wait_ms
(
500
);
/* Cool down */
usb_
clear_hub_feature
(
dev
,
C_HUB_OVER_CURRENT
);
clear_hub_feature
(
dev
,
C_HUB_OVER_CURRENT
);
usb_
hub_power_on
(
hub
);
hub_power_on
(
hub
);
}
}
}
}
up
(
&
hub
->
khubd_sem
);
up
(
&
hub
->
khubd_sem
);
...
@@ -1086,7 +1125,7 @@ static void usb_hub_events(void)
...
@@ -1086,7 +1125,7 @@ static void usb_hub_events(void)
spin_unlock_irqrestore
(
&
hub_event_lock
,
flags
);
spin_unlock_irqrestore
(
&
hub_event_lock
,
flags
);
}
}
static
int
usb_
hub_thread
(
void
*
__hub
)
static
int
hub_thread
(
void
*
__hub
)
{
{
/*
/*
* This thread doesn't need any user-level access,
* This thread doesn't need any user-level access,
...
@@ -1098,13 +1137,13 @@ static int usb_hub_thread(void *__hub)
...
@@ -1098,13 +1137,13 @@ static int usb_hub_thread(void *__hub)
/* Send me a signal to get me die (for debugging) */
/* Send me a signal to get me die (for debugging) */
do
{
do
{
usb_
hub_events
();
hub_events
();
wait_event_interruptible
(
khubd_wait
,
!
list_empty
(
&
hub_event_list
));
wait_event_interruptible
(
khubd_wait
,
!
list_empty
(
&
hub_event_list
));
if
(
current
->
flags
&
PF_FREEZE
)
if
(
current
->
flags
&
PF_FREEZE
)
refrigerator
(
PF_IOTHREAD
);
refrigerator
(
PF_IOTHREAD
);
}
while
(
!
signal_pending
(
current
));
}
while
(
!
signal_pending
(
current
));
dbg
(
"
usb_
hub_thread exiting"
);
dbg
(
"hub_thread exiting"
);
complete_and_exit
(
&
khubd_exited
,
0
);
complete_and_exit
(
&
khubd_exited
,
0
);
}
}
...
@@ -1139,7 +1178,7 @@ int usb_hub_init(void)
...
@@ -1139,7 +1178,7 @@ int usb_hub_init(void)
return
-
1
;
return
-
1
;
}
}
pid
=
kernel_thread
(
usb_
hub_thread
,
NULL
,
pid
=
kernel_thread
(
hub_thread
,
NULL
,
CLONE_FS
|
CLONE_FILES
|
CLONE_SIGHAND
);
CLONE_FS
|
CLONE_FILES
|
CLONE_SIGHAND
);
if
(
pid
>=
0
)
{
if
(
pid
>=
0
)
{
khubd_pid
=
pid
;
khubd_pid
=
pid
;
...
@@ -1149,7 +1188,7 @@ int usb_hub_init(void)
...
@@ -1149,7 +1188,7 @@ int usb_hub_init(void)
/* Fall through if kernel_thread failed */
/* Fall through if kernel_thread failed */
usb_deregister
(
&
hub_driver
);
usb_deregister
(
&
hub_driver
);
err
(
"failed to start
usb_
hub_thread"
);
err
(
"failed to start hub_thread"
);
return
-
1
;
return
-
1
;
}
}
...
@@ -1212,8 +1251,8 @@ int usb_physical_reset_device(struct usb_device *dev)
...
@@ -1212,8 +1251,8 @@ int usb_physical_reset_device(struct usb_device *dev)
down
(
&
usb_address0_sem
);
down
(
&
usb_address0_sem
);
/* Send a reset to the device */
/* Send a reset to the device */
if
(
usb_
hub_port_reset
(
parent
,
port
,
dev
,
HUB_SHORT_RESET_TIME
))
{
if
(
hub_port_reset
(
parent
,
port
,
dev
,
HUB_SHORT_RESET_TIME
))
{
usb_
hub_port_disable
(
parent
,
port
);
hub_port_disable
(
parent
,
port
);
up
(
&
usb_address0_sem
);
up
(
&
usb_address0_sem
);
kfree
(
descriptor
);
kfree
(
descriptor
);
return
(
-
ENODEV
);
return
(
-
ENODEV
);
...
@@ -1223,7 +1262,7 @@ int usb_physical_reset_device(struct usb_device *dev)
...
@@ -1223,7 +1262,7 @@ int usb_physical_reset_device(struct usb_device *dev)
ret
=
usb_set_address
(
dev
);
ret
=
usb_set_address
(
dev
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
err
(
"USB device not accepting new address (error=%d)"
,
ret
);
err
(
"USB device not accepting new address (error=%d)"
,
ret
);
usb_
hub_port_disable
(
parent
,
port
);
hub_port_disable
(
parent
,
port
);
up
(
&
usb_address0_sem
);
up
(
&
usb_address0_sem
);
kfree
(
descriptor
);
kfree
(
descriptor
);
return
ret
;
return
ret
;
...
...
drivers/usb/core/hub.h
View file @
e1f015ee
...
@@ -174,7 +174,12 @@ struct usb_hub {
...
@@ -174,7 +174,12 @@ struct usb_hub {
struct
urb
*
urb
;
/* for interrupt polling pipe */
struct
urb
*
urb
;
/* for interrupt polling pipe */
/* buffer for urb ... 1 bit each for hub and children, rounded up */
/* buffer for urb ... 1 bit each for hub and children, rounded up */
char
buffer
[(
USB_MAXCHILDREN
+
1
+
7
)
/
8
];
char
(
*
buffer
)[(
USB_MAXCHILDREN
+
1
+
7
)
/
8
];
dma_addr_t
buffer_dma
;
/* DMA address for buffer */
union
{
struct
usb_hub_status
hub
;
struct
usb_port_status
port
;
}
*
status
;
/* buffer for status reports */
int
error
;
/* last reported error */
int
error
;
/* last reported error */
int
nerrors
;
/* track consecutive errors */
int
nerrors
;
/* track consecutive errors */
...
...
drivers/usb/gadget/net2280.c
View file @
e1f015ee
...
@@ -20,10 +20,12 @@
...
@@ -20,10 +20,12 @@
* short OUT transfers happen.) Drivers can use the req->no_interrupt
* short OUT transfers happen.) Drivers can use the req->no_interrupt
* hint to completely eliminate some IRQs, if a later IRQ is guaranteed
* hint to completely eliminate some IRQs, if a later IRQ is guaranteed
* and DMA chaining is enabled.
* and DMA chaining is enabled.
*
* Note that almost all the errata workarounds here are only needed for
* rev1 chips. Rev1a silicon (0110) fixes almost all of them.
*/
*/
// #define NET2280_DMA_OUT_WORKAROUND
#define USE_DMA_CHAINING
// #define USE_DMA_CHAINING
/*
/*
...
@@ -180,6 +182,13 @@ net2280_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
...
@@ -180,6 +182,13 @@ net2280_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
* kicking in the "toggle-irrelevant" mode.
* kicking in the "toggle-irrelevant" mode.
*/
*/
tmp
=
USB_ENDPOINT_XFER_BULK
;
tmp
=
USB_ENDPOINT_XFER_BULK
;
}
else
if
(
tmp
==
USB_ENDPOINT_XFER_BULK
)
{
/* catch some particularly blatant driver bugs */
if
((
dev
->
gadget
.
speed
==
USB_SPEED_HIGH
&&
max
!=
512
)
||
(
dev
->
gadget
.
speed
==
USB_SPEED_FULL
&&
max
>
64
))
return
-
ERANGE
;
}
}
ep
->
is_iso
=
(
tmp
==
USB_ENDPOINT_XFER_ISOC
)
?
1
:
0
;
ep
->
is_iso
=
(
tmp
==
USB_ENDPOINT_XFER_ISOC
)
?
1
:
0
;
tmp
<<=
ENDPOINT_TYPE
;
tmp
<<=
ENDPOINT_TYPE
;
...
@@ -252,9 +261,6 @@ static int handshake (u32 *ptr, u32 mask, u32 done, int usec)
...
@@ -252,9 +261,6 @@ static int handshake (u32 *ptr, u32 mask, u32 done, int usec)
udelay
(
1
);
udelay
(
1
);
usec
--
;
usec
--
;
}
while
(
usec
>
0
);
}
while
(
usec
>
0
);
#ifdef DEBUG
if
(
done
==
0
)
dump_stack
();
/* ignore out_flush timeout */
#endif
return
-
ETIMEDOUT
;
return
-
ETIMEDOUT
;
}
}
...
@@ -917,6 +923,8 @@ net2280_queue (struct usb_ep *_ep, struct usb_request *_req, int gfp_flags)
...
@@ -917,6 +923,8 @@ net2280_queue (struct usb_ep *_ep, struct usb_request *_req, int gfp_flags)
*/
*/
if
(
read_fifo
(
ep
,
req
))
{
if
(
read_fifo
(
ep
,
req
))
{
done
(
ep
,
req
,
0
);
done
(
ep
,
req
,
0
);
if
(
ep
->
num
==
0
)
allow_status
(
ep
);
/* don't queue it */
/* don't queue it */
req
=
0
;
req
=
0
;
}
else
}
else
...
@@ -1194,9 +1202,12 @@ net2280_set_halt (struct usb_ep *_ep, int value)
...
@@ -1194,9 +1202,12 @@ net2280_set_halt (struct usb_ep *_ep, int value)
VDEBUG
(
ep
->
dev
,
"%s %s halt
\n
"
,
_ep
->
name
,
value
?
"set"
:
"clear"
);
VDEBUG
(
ep
->
dev
,
"%s %s halt
\n
"
,
_ep
->
name
,
value
?
"set"
:
"clear"
);
/* set/clear, then synch memory views with the device */
/* set/clear, then synch memory views with the device */
if
(
value
)
if
(
value
)
{
set_halt
(
ep
);
if
(
ep
->
num
==
0
)
ep
->
dev
->
protocol_stall
=
1
;
else
else
set_halt
(
ep
);
}
else
clear_halt
(
ep
);
clear_halt
(
ep
);
(
void
)
readl
(
&
ep
->
regs
->
ep_rsp
);
(
void
)
readl
(
&
ep
->
regs
->
ep_rsp
);
...
@@ -2042,6 +2053,7 @@ static void handle_ep_small (struct net2280_ep *ep)
...
@@ -2042,6 +2053,7 @@ static void handle_ep_small (struct net2280_ep *ep)
* can decide to stall ep0 after that done() returns,
* can decide to stall ep0 after that done() returns,
* from non-irq context
* from non-irq context
*/
*/
if
(
!
ep
->
stopped
)
allow_status
(
ep
);
allow_status
(
ep
);
req
=
0
;
req
=
0
;
}
else
{
}
else
{
...
...
drivers/usb/host/ohci-q.c
View file @
e1f015ee
...
@@ -377,12 +377,8 @@ static struct ed *ed_get (
...
@@ -377,12 +377,8 @@ static struct ed *ed_get (
ed
->
type
=
type
;
ed
->
type
=
type
;
}
}
/* FIXME: Don't do this without knowing it's safe to clobber this
/* NOTE: only ep0 currently needs this "re"init logic, during
* state/mode info. Currently the upper layers don't support such
* enumeration (after set_address, or if ep0 maxpacket >8).
* guarantees; we're lucky changing config/altsetting is rare.
* The state/mode info also changes during enumeration: set_address
* uses the 'wrong' device address, and ep0 maxpacketsize will often
* improve on the initial value.
*/
*/
if
(
ed
->
state
==
ED_IDLE
)
{
if
(
ed
->
state
==
ED_IDLE
)
{
u32
info
;
u32
info
;
...
...
drivers/usb/image/hpusbscsi.c
View file @
e1f015ee
...
@@ -45,7 +45,7 @@ hpusbscsi_usb_probe(struct usb_interface *intf,
...
@@ -45,7 +45,7 @@ hpusbscsi_usb_probe(struct usb_interface *intf,
struct
usb_host_interface
*
altsetting
=
intf
->
altsetting
;
struct
usb_host_interface
*
altsetting
=
intf
->
altsetting
;
struct
hpusbscsi
*
new
;
struct
hpusbscsi
*
new
;
int
error
=
-
ENOMEM
;
int
error
=
-
ENOMEM
;
int
i
,
result
;
int
i
;
if
(
altsetting
->
desc
.
bNumEndpoints
!=
3
)
{
if
(
altsetting
->
desc
.
bNumEndpoints
!=
3
)
{
printk
(
KERN_ERR
"Wrong number of endpoints
\n
"
);
printk
(
KERN_ERR
"Wrong number of endpoints
\n
"
);
...
...
drivers/usb/media/vicam.c
View file @
e1f015ee
...
@@ -1101,6 +1101,52 @@ static int vicam_read_proc_gain(char *page, char **start, off_t off,
...
@@ -1101,6 +1101,52 @@ static int vicam_read_proc_gain(char *page, char **start, off_t off,
((
struct
vicam_camera
*
)
data
)
->
gain
);
((
struct
vicam_camera
*
)
data
)
->
gain
);
}
}
static
int
vicam_write_proc_shutter
(
struct
file
*
file
,
const
char
*
buffer
,
unsigned
long
count
,
void
*
data
)
{
u16
stmp
;
char
kbuf
[
8
];
struct
vicam_camera
*
cam
=
(
struct
vicam_camera
*
)
data
;
if
(
count
>
6
)
return
-
EINVAL
;
if
(
copy_from_user
(
kbuf
,
buffer
,
count
))
return
-
EFAULT
;
stmp
=
(
u16
)
simple_strtoul
(
kbuf
,
NULL
,
10
);
if
(
stmp
<
4
||
stmp
>
32000
)
return
-
EINVAL
;
cam
->
shutter_speed
=
stmp
;
return
count
;
}
static
int
vicam_write_proc_gain
(
struct
file
*
file
,
const
char
*
buffer
,
unsigned
long
count
,
void
*
data
)
{
u16
gtmp
;
char
kbuf
[
8
];
struct
vicam_camera
*
cam
=
(
struct
vicam_camera
*
)
data
;
if
(
count
>
4
)
return
-
EINVAL
;
if
(
copy_from_user
(
kbuf
,
buffer
,
count
))
return
-
EFAULT
;
gtmp
=
(
u16
)
simple_strtoul
(
kbuf
,
NULL
,
10
);
if
(
gtmp
>
255
)
return
-
EINVAL
;
cam
->
gain
=
gtmp
;
return
count
;
}
static
void
static
void
vicam_create_proc_root
(
void
)
vicam_create_proc_root
(
void
)
{
{
...
@@ -1142,18 +1188,21 @@ vicam_create_proc_entry(struct vicam_camera *cam)
...
@@ -1142,18 +1188,21 @@ vicam_create_proc_entry(struct vicam_camera *cam)
if
(
!
cam
->
proc_dir
)
if
(
!
cam
->
proc_dir
)
return
;
// FIXME: We should probably return an error here
return
;
// FIXME: We should probably return an error here
ent
=
ent
=
create_proc_entry
(
"shutter"
,
S_IFREG
|
S_IRUGO
|
S_IWUSR
,
create_proc_entry
(
"shutter"
,
S_IFREG
|
S_IRUGO
,
cam
->
proc_dir
);
cam
->
proc_dir
);
if
(
ent
)
{
if
(
ent
)
{
ent
->
data
=
cam
;
ent
->
data
=
cam
;
ent
->
read_proc
=
vicam_read_proc_shutter
;
ent
->
read_proc
=
vicam_read_proc_shutter
;
ent
->
write_proc
=
vicam_write_proc_shutter
;
ent
->
size
=
64
;
ent
->
size
=
64
;
}
}
ent
=
create_proc_entry
(
"gain"
,
S_IFREG
|
S_IRUGO
,
cam
->
proc_dir
);
ent
=
create_proc_entry
(
"gain"
,
S_IFREG
|
S_IRUGO
|
S_IWUSR
,
if
(
ent
)
{
cam
->
proc_dir
);
if
(
ent
)
{
ent
->
data
=
cam
;
ent
->
data
=
cam
;
ent
->
read_proc
=
vicam_read_proc_gain
;
ent
->
read_proc
=
vicam_read_proc_gain
;
ent
->
write_proc
=
vicam_write_proc_gain
;
ent
->
size
=
64
;
ent
->
size
=
64
;
}
}
}
}
...
...
drivers/usb/net/catc.c
View file @
e1f015ee
...
@@ -63,6 +63,8 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
...
@@ -63,6 +63,8 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION
(
DRIVER_DESC
);
MODULE_DESCRIPTION
(
DRIVER_DESC
);
MODULE_LICENSE
(
"GPL"
);
MODULE_LICENSE
(
"GPL"
);
static
const
char
driver_name
[]
=
"catc"
;
/*
/*
* Some defines.
* Some defines.
*/
*/
...
@@ -677,7 +679,7 @@ static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
...
@@ -677,7 +679,7 @@ static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
/* get driver info */
/* get driver info */
case
ETHTOOL_GDRVINFO
:
{
case
ETHTOOL_GDRVINFO
:
{
struct
ethtool_drvinfo
info
=
{
ETHTOOL_GDRVINFO
};
struct
ethtool_drvinfo
info
=
{
ETHTOOL_GDRVINFO
};
strncpy
(
info
.
driver
,
SHORT_DRIVER_DESC
,
ETHTOOL_BUSINFO_LEN
);
strncpy
(
info
.
driver
,
driver_name
,
ETHTOOL_BUSINFO_LEN
);
strncpy
(
info
.
version
,
DRIVER_VERSION
,
ETHTOOL_BUSINFO_LEN
);
strncpy
(
info
.
version
,
DRIVER_VERSION
,
ETHTOOL_BUSINFO_LEN
);
usb_make_path
(
catc
->
usbdev
,
info
.
bus_info
,
sizeof
info
.
bus_info
);
usb_make_path
(
catc
->
usbdev
,
info
.
bus_info
,
sizeof
info
.
bus_info
);
if
(
copy_to_user
(
useraddr
,
&
info
,
sizeof
(
info
)))
if
(
copy_to_user
(
useraddr
,
&
info
,
sizeof
(
info
)))
...
@@ -978,7 +980,7 @@ MODULE_DEVICE_TABLE(usb, catc_id_table);
...
@@ -978,7 +980,7 @@ MODULE_DEVICE_TABLE(usb, catc_id_table);
static
struct
usb_driver
catc_driver
=
{
static
struct
usb_driver
catc_driver
=
{
.
owner
=
THIS_MODULE
,
.
owner
=
THIS_MODULE
,
.
name
=
"catc"
,
.
name
=
driver_name
,
.
probe
=
catc_probe
,
.
probe
=
catc_probe
,
.
disconnect
=
catc_disconnect
,
.
disconnect
=
catc_disconnect
,
.
id_table
=
catc_id_table
,
.
id_table
=
catc_id_table
,
...
...
drivers/usb/net/kaweth.c
View file @
e1f015ee
...
@@ -114,6 +114,8 @@ MODULE_AUTHOR("Michael Zappe <zapman@interlan.net>, Stephane Alnet <stephane@u-p
...
@@ -114,6 +114,8 @@ MODULE_AUTHOR("Michael Zappe <zapman@interlan.net>, Stephane Alnet <stephane@u-p
MODULE_DESCRIPTION
(
"KL5USB101 USB Ethernet driver"
);
MODULE_DESCRIPTION
(
"KL5USB101 USB Ethernet driver"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_LICENSE
(
"GPL"
);
static
const
char
driver_name
[]
=
"kaweth"
;
static
int
kaweth_probe
(
static
int
kaweth_probe
(
struct
usb_interface
*
intf
,
struct
usb_interface
*
intf
,
const
struct
usb_device_id
*
id
/* from id_table */
const
struct
usb_device_id
*
id
/* from id_table */
...
@@ -169,7 +171,7 @@ MODULE_DEVICE_TABLE (usb, usb_klsi_table);
...
@@ -169,7 +171,7 @@ MODULE_DEVICE_TABLE (usb, usb_klsi_table);
****************************************************************/
****************************************************************/
static
struct
usb_driver
kaweth_driver
=
{
static
struct
usb_driver
kaweth_driver
=
{
.
owner
=
THIS_MODULE
,
.
owner
=
THIS_MODULE
,
.
name
=
"kaweth"
,
.
name
=
driver_name
,
.
probe
=
kaweth_probe
,
.
probe
=
kaweth_probe
,
.
disconnect
=
kaweth_disconnect
,
.
disconnect
=
kaweth_disconnect
,
.
id_table
=
usb_klsi_table
,
.
id_table
=
usb_klsi_table
,
...
@@ -670,7 +672,7 @@ static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
...
@@ -670,7 +672,7 @@ static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
switch
(
ethcmd
)
{
switch
(
ethcmd
)
{
case
ETHTOOL_GDRVINFO
:
{
case
ETHTOOL_GDRVINFO
:
{
struct
ethtool_drvinfo
info
=
{
ETHTOOL_GDRVINFO
};
struct
ethtool_drvinfo
info
=
{
ETHTOOL_GDRVINFO
};
strlcpy
(
info
.
driver
,
"kaweth"
,
sizeof
(
info
.
driver
));
strlcpy
(
info
.
driver
,
driver_name
,
sizeof
(
info
.
driver
));
if
(
copy_to_user
(
useraddr
,
&
info
,
sizeof
(
info
)))
if
(
copy_to_user
(
useraddr
,
&
info
,
sizeof
(
info
)))
return
-
EFAULT
;
return
-
EFAULT
;
return
0
;
return
0
;
...
...
drivers/usb/net/pegasus.c
View file @
e1f015ee
/*
/*
* Copyright (c) 1999-200
2
Petko Manolov (petkan@users.sourceforge.net)
* Copyright (c) 1999-200
3
Petko Manolov (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 version 2 as
* it under the terms of the GNU General Public License version 2 as
...
@@ -45,7 +45,7 @@
...
@@ -45,7 +45,7 @@
/*
/*
* Version Information
* Version Information
*/
*/
#define DRIVER_VERSION "v0.5.1
0 (2003/04/01
)"
#define DRIVER_VERSION "v0.5.1
2 (2003/06/06
)"
#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"
...
@@ -564,7 +564,14 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs)
...
@@ -564,7 +564,14 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs)
dbg
(
"%s: reset MAC"
,
net
->
name
);
dbg
(
"%s: reset MAC"
,
net
->
name
);
pegasus
->
flags
&=
~
PEGASUS_RX_BUSY
;
pegasus
->
flags
&=
~
PEGASUS_RX_BUSY
;
break
;
break
;
case
-
EPIPE
:
/* stall, or disconnect from TT */
/* FIXME schedule work to clear the halt */
warn
(
"%s: no rx stall recovery"
,
net
->
name
);
return
;
case
-
ENOENT
:
case
-
ENOENT
:
case
-
ECONNRESET
:
case
-
ESHUTDOWN
:
dbg
(
"%s: rx unlink, %d"
,
net
->
name
,
urb
->
status
);
return
;
return
;
default:
default:
dbg
(
"%s: RX status %d"
,
net
->
name
,
urb
->
status
);
dbg
(
"%s: RX status %d"
,
net
->
name
,
urb
->
status
);
...
@@ -604,6 +611,9 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs)
...
@@ -604,6 +611,9 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs)
pegasus
->
stats
.
rx_packets
++
;
pegasus
->
stats
.
rx_packets
++
;
pegasus
->
stats
.
rx_bytes
+=
pkt_len
;
pegasus
->
stats
.
rx_bytes
+=
pkt_len
;
if
(
pegasus
->
flags
&
PEGASUS_UNPLUG
)
return
;
spin_lock
(
&
pegasus
->
rx_pool_lock
);
spin_lock
(
&
pegasus
->
rx_pool_lock
);
pegasus
->
rx_skb
=
pull_skb
(
pegasus
);
pegasus
->
rx_skb
=
pull_skb
(
pegasus
);
spin_unlock
(
&
pegasus
->
rx_pool_lock
);
spin_unlock
(
&
pegasus
->
rx_pool_lock
);
...
@@ -631,24 +641,24 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs)
...
@@ -631,24 +641,24 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs)
static
void
rx_fixup
(
unsigned
long
data
)
static
void
rx_fixup
(
unsigned
long
data
)
{
{
pegasus_t
*
pegasus
;
pegasus_t
*
pegasus
;
unsigned
long
flags
;
pegasus
=
(
pegasus_t
*
)
data
;
pegasus
=
(
pegasus_t
*
)
data
;
if
(
pegasus
->
flags
&
PEGASUS_UNPLUG
)
return
;
spin_lock_irq
(
&
pegasus
->
rx_pool_lock
);
spin_lock_irq
save
(
&
pegasus
->
rx_pool_lock
,
flags
);
fill_skb_pool
(
pegasus
);
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
==
NULL
)
{
spin_lock_irq
(
&
pegasus
->
rx_pool_lock
);
pegasus
->
rx_skb
=
pull_skb
(
pegasus
);
pegasus
->
rx_skb
=
pull_skb
(
pegasus
);
spin_unlock_irq
(
&
pegasus
->
rx_pool_lock
);
}
}
if
(
pegasus
->
rx_skb
==
NULL
)
{
if
(
pegasus
->
rx_skb
==
NULL
)
{
warn
(
"wow, low on memory"
);
warn
(
"wow, low on memory"
);
tasklet_schedule
(
&
pegasus
->
rx_tl
);
tasklet_schedule
(
&
pegasus
->
rx_tl
);
return
;
goto
done
;
}
}
usb_fill_bulk_urb
(
pegasus
->
rx_urb
,
pegasus
->
usb
,
usb_fill_bulk_urb
(
pegasus
->
rx_urb
,
pegasus
->
usb
,
usb_rcvbulkpipe
(
pegasus
->
usb
,
1
),
usb_rcvbulkpipe
(
pegasus
->
usb
,
1
),
...
@@ -661,23 +671,41 @@ static void rx_fixup(unsigned long data)
...
@@ -661,23 +671,41 @@ static void rx_fixup(unsigned long data)
}
else
{
}
else
{
pegasus
->
flags
&=
~
PEGASUS_RX_URB_FAIL
;
pegasus
->
flags
&=
~
PEGASUS_RX_URB_FAIL
;
}
}
done:
spin_unlock_irqrestore
(
&
pegasus
->
rx_pool_lock
,
flags
);
}
}
static
void
write_bulk_callback
(
struct
urb
*
urb
,
struct
pt_regs
*
regs
)
static
void
write_bulk_callback
(
struct
urb
*
urb
,
struct
pt_regs
*
regs
)
{
{
pegasus_t
*
pegasus
=
urb
->
context
;
pegasus_t
*
pegasus
=
urb
->
context
;
struct
net_device
*
net
=
pegasus
->
net
;
if
(
!
pegasus
||
!
(
pegasus
->
flags
&
PEGASUS_RUNNING
))
if
(
!
pegasus
||
!
(
pegasus
->
flags
&
PEGASUS_RUNNING
))
return
;
return
;
if
(
!
netif_device_present
(
pegasus
->
net
))
if
(
!
netif_device_present
(
net
))
return
;
return
;
if
(
urb
->
status
)
switch
(
urb
->
status
)
{
info
(
"%s: TX status %d"
,
pegasus
->
net
->
name
,
urb
->
status
);
case
-
EPIPE
:
/* FIXME schedule_work() to clear the tx halt */
netif_stop_queue
(
net
);
warn
(
"%s: no tx stall recovery"
,
net
->
name
);
return
;
case
-
ENOENT
:
case
-
ECONNRESET
:
case
-
ESHUTDOWN
:
dbg
(
"%s: tx unlink, %d"
,
net
->
name
,
urb
->
status
);
return
;
default:
info
(
"%s: TX status %d"
,
net
->
name
,
urb
->
status
);
/* FALL THROUGH */
case
0
:
break
;
}
pegasus
->
net
->
trans_start
=
jiffies
;
net
->
trans_start
=
jiffies
;
netif_wake_queue
(
pegasus
->
net
);
netif_wake_queue
(
net
);
}
}
static
void
intr_callback
(
struct
urb
*
urb
,
struct
pt_regs
*
regs
)
static
void
intr_callback
(
struct
urb
*
urb
,
struct
pt_regs
*
regs
)
...
@@ -754,8 +782,16 @@ static int pegasus_start_xmit(struct sk_buff *skb, struct net_device *net)
...
@@ -754,8 +782,16 @@ static int pegasus_start_xmit(struct sk_buff *skb, struct net_device *net)
write_bulk_callback
,
pegasus
);
write_bulk_callback
,
pegasus
);
if
((
res
=
usb_submit_urb
(
pegasus
->
tx_urb
,
GFP_ATOMIC
)))
{
if
((
res
=
usb_submit_urb
(
pegasus
->
tx_urb
,
GFP_ATOMIC
)))
{
warn
(
"failed tx_urb %d"
,
res
);
warn
(
"failed tx_urb %d"
,
res
);
switch
(
res
)
{
case
-
EPIPE
:
/* stall, or disconnect from TT */
/* cleanup should already have been scheduled */
break
;
case
-
ENODEV
:
/* disconnect() upcoming */
break
;
default:
pegasus
->
stats
.
tx_errors
++
;
pegasus
->
stats
.
tx_errors
++
;
netif_start_queue
(
net
);
netif_start_queue
(
net
);
}
}
else
{
}
else
{
pegasus
->
stats
.
tx_packets
++
;
pegasus
->
stats
.
tx_packets
++
;
pegasus
->
stats
.
tx_bytes
+=
skb
->
len
;
pegasus
->
stats
.
tx_bytes
+=
skb
->
len
;
...
@@ -903,6 +939,7 @@ static int pegasus_close(struct net_device *net)
...
@@ -903,6 +939,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
);
tasklet_kill
(
&
pegasus
->
rx_tl
);
unlink_all_urbs
(
pegasus
);
unlink_all_urbs
(
pegasus
);
return
0
;
return
0
;
...
@@ -920,11 +957,15 @@ static int pegasus_ethtool_ioctl(struct net_device *dev, void *useraddr)
...
@@ -920,11 +957,15 @@ static int pegasus_ethtool_ioctl(struct net_device *dev, void *useraddr)
switch
(
ethcmd
)
{
switch
(
ethcmd
)
{
/* get driver-specific version/etc. info */
/* get driver-specific version/etc. info */
case
ETHTOOL_GDRVINFO
:{
case
ETHTOOL_GDRVINFO
:{
struct
ethtool_drvinfo
info
=
{
ETHTOOL_GDRVINFO
};
struct
ethtool_drvinfo
info
;
strlcpy
(
info
.
driver
,
driver_name
,
memset
(
&
info
,
0
,
sizeof
(
info
));
sizeof
(
info
.
driver
));
info
.
cmd
=
ETHTOOL_GDRVINFO
;
strlcpy
(
info
.
version
,
DRIVER_VERSION
,
strncpy
(
info
.
driver
,
driver_name
,
sizeof
(
info
.
version
));
sizeof
(
info
.
driver
)
-
1
);
strncpy
(
info
.
version
,
DRIVER_VERSION
,
sizeof
(
info
.
version
)
-
1
);
usb_make_path
(
pegasus
->
usb
,
info
.
bus_info
,
sizeof
(
info
.
bus_info
));
if
(
copy_to_user
(
useraddr
,
&
info
,
sizeof
(
info
)))
if
(
copy_to_user
(
useraddr
,
&
info
,
sizeof
(
info
)))
return
-
EFAULT
;
return
-
EFAULT
;
return
0
;
return
0
;
...
@@ -993,12 +1034,15 @@ static int pegasus_ethtool_ioctl(struct net_device *net, void *uaddr)
...
@@ -993,12 +1034,15 @@ static int pegasus_ethtool_ioctl(struct net_device *net, void *uaddr)
return
-
EFAULT
;
return
-
EFAULT
;
switch
(
cmd
)
{
switch
(
cmd
)
{
case
ETHTOOL_GDRVINFO
:{
case
ETHTOOL_GDRVINFO
:{
struct
ethtool_drvinfo
info
=
{
ETHTOOL_GDRVINFO
};
struct
ethtool_drvinfo
info
;
strncpy
(
info
.
driver
,
driver_name
,
sizeof
info
.
driver
);
memset
(
&
info
,
0
,
sizeof
(
info
));
info
.
cmd
=
ETHTOOL_GDRVINFO
;
strncpy
(
info
.
driver
,
driver_name
,
sizeof
(
info
.
driver
)
-
1
);
strncpy
(
info
.
version
,
DRIVER_VERSION
,
strncpy
(
info
.
version
,
DRIVER_VERSION
,
ETHTOOL_BUSINFO_LEN
);
sizeof
(
info
.
version
)
-
1
);
usb_make_path
(
pegasus
->
usb
,
info
.
bus_info
,
usb_make_path
(
pegasus
->
usb
,
info
.
bus_info
,
sizeof
info
.
bus_info
);
sizeof
(
info
.
bus_info
)
);
if
(
copy_to_user
(
uaddr
,
&
info
,
sizeof
(
info
)))
if
(
copy_to_user
(
uaddr
,
&
info
,
sizeof
(
info
)))
return
-
EFAULT
;
return
-
EFAULT
;
return
0
;
return
0
;
...
@@ -1006,14 +1050,19 @@ static int pegasus_ethtool_ioctl(struct net_device *net, void *uaddr)
...
@@ -1006,14 +1050,19 @@ static int pegasus_ethtool_ioctl(struct net_device *net, void *uaddr)
case
ETHTOOL_GSET
:{
case
ETHTOOL_GSET
:{
struct
ethtool_cmd
ecmd
;
struct
ethtool_cmd
ecmd
;
short
lpa
,
bmcr
;
short
lpa
,
bmcr
;
u8
port
;
memset
(
&
ecmd
,
0
,
sizeof
ecmd
);
memset
(
&
ecmd
,
0
,
sizeof
(
ecmd
)
);
ecmd
.
supported
=
(
SUPPORTED_10baseT_Half
|
ecmd
.
supported
=
(
SUPPORTED_10baseT_Half
|
SUPPORTED_10baseT_Full
|
SUPPORTED_10baseT_Full
|
SUPPORTED_100baseT_Half
|
SUPPORTED_100baseT_Half
|
SUPPORTED_100baseT_Full
|
SUPPORTED_100baseT_Full
|
SUPPORTED_Autoneg
|
SUPPORTED_Autoneg
|
SUPPORTED_TP
|
SUPPORTED_MII
);
SUPPORTED_TP
|
SUPPORTED_MII
);
get_registers
(
pegasus
,
Reg7b
,
1
,
&
port
);
if
(
port
==
0
)
ecmd
.
port
=
PORT_MII
;
else
ecmd
.
port
=
PORT_TP
;
ecmd
.
port
=
PORT_TP
;
ecmd
.
transceiver
=
XCVR_INTERNAL
;
ecmd
.
transceiver
=
XCVR_INTERNAL
;
ecmd
.
phy_address
=
pegasus
->
phy
;
ecmd
.
phy_address
=
pegasus
->
phy
;
...
@@ -1132,6 +1181,9 @@ static inline void setup_pegasus_II(pegasus_t * pegasus)
...
@@ -1132,6 +1181,9 @@ static inline void setup_pegasus_II(pegasus_t * pegasus)
set_register
(
pegasus
,
Reg1d
,
0
);
set_register
(
pegasus
,
Reg1d
,
0
);
set_register
(
pegasus
,
Reg7b
,
1
);
set_register
(
pegasus
,
Reg7b
,
1
);
mdelay
(
100
);
mdelay
(
100
);
if
((
pegasus
->
features
&
HAS_HOME_PNA
)
&&
mii_mode
)
set_register
(
pegasus
,
Reg7b
,
0
);
else
set_register
(
pegasus
,
Reg7b
,
2
);
set_register
(
pegasus
,
Reg7b
,
2
);
set_register
(
pegasus
,
0x83
,
data
);
set_register
(
pegasus
,
0x83
,
data
);
...
@@ -1253,7 +1305,6 @@ static void pegasus_disconnect(struct usb_interface *intf)
...
@@ -1253,7 +1305,6 @@ static void pegasus_disconnect(struct usb_interface *intf)
pegasus
->
flags
|=
PEGASUS_UNPLUG
;
pegasus
->
flags
|=
PEGASUS_UNPLUG
;
unregister_netdev
(
pegasus
->
net
);
unregister_netdev
(
pegasus
->
net
);
usb_put_dev
(
interface_to_usbdev
(
intf
));
usb_put_dev
(
interface_to_usbdev
(
intf
));
unlink_all_urbs
(
pegasus
);
free_all_urbs
(
pegasus
);
free_all_urbs
(
pegasus
);
free_skb_pool
(
pegasus
);
free_skb_pool
(
pegasus
);
if
(
pegasus
->
rx_skb
)
if
(
pegasus
->
rx_skb
)
...
@@ -1263,7 +1314,6 @@ static void pegasus_disconnect(struct usb_interface *intf)
...
@@ -1263,7 +1314,6 @@ static void pegasus_disconnect(struct usb_interface *intf)
}
}
static
struct
usb_driver
pegasus_driver
=
{
static
struct
usb_driver
pegasus_driver
=
{
.
owner
=
THIS_MODULE
,
.
name
=
driver_name
,
.
name
=
driver_name
,
.
probe
=
pegasus_probe
,
.
probe
=
pegasus_probe
,
.
disconnect
=
pegasus_disconnect
,
.
disconnect
=
pegasus_disconnect
,
...
...
drivers/usb/net/pegasus.h
View file @
e1f015ee
/*
/*
* Copyright (c) 1999-200
2
Petko Manolov - Petkan (petkan@users.sourceforge.net)
* Copyright (c) 1999-200
3
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 version 2 as published
* it under the terms of the GNU General Public License version 2 as published
...
@@ -129,6 +129,7 @@ struct usb_eth_dev {
...
@@ -129,6 +129,7 @@ struct usb_eth_dev {
#define VENDOR_ELCON 0x0db7
#define VENDOR_ELCON 0x0db7
#define VENDOR_ELSA 0x05cc
#define VENDOR_ELSA 0x05cc
#define VENDOR_HAWKING 0x0e66
#define VENDOR_HAWKING 0x0e66
#define VENDOR_HP 0x03f0
#define VENDOR_IODATA 0x04bb
#define VENDOR_IODATA 0x04bb
#define VENDOR_KINGSTON 0x0951
#define VENDOR_KINGSTON 0x0951
#define VENDOR_LANEED 0x056e
#define VENDOR_LANEED 0x056e
...
@@ -223,6 +224,8 @@ PEGASUS_DEV( "Elsa Micolink USB2Ethernet", VENDOR_ELSA, 0x3000,
...
@@ -223,6 +224,8 @@ PEGASUS_DEV( "Elsa Micolink USB2Ethernet", VENDOR_ELSA, 0x3000,
DEFAULT_GPIO_RESET
)
DEFAULT_GPIO_RESET
)
PEGASUS_DEV
(
"Hawking UF100 10/100 Ethernet"
,
VENDOR_HAWKING
,
0x400c
,
PEGASUS_DEV
(
"Hawking UF100 10/100 Ethernet"
,
VENDOR_HAWKING
,
0x400c
,
DEFAULT_GPIO_RESET
|
PEGASUS_II
)
DEFAULT_GPIO_RESET
|
PEGASUS_II
)
PEGASUS_DEV
(
"HP hn210c Ethernet USB"
,
VENDOR_HP
,
0x811c
,
DEFAULT_GPIO_RESET
|
PEGASUS_II
)
PEGASUS_DEV
(
"IO DATA USB ET/TX"
,
VENDOR_IODATA
,
0x0904
,
PEGASUS_DEV
(
"IO DATA USB ET/TX"
,
VENDOR_IODATA
,
0x0904
,
DEFAULT_GPIO_RESET
)
DEFAULT_GPIO_RESET
)
PEGASUS_DEV
(
"IO DATA USB ET/TX-S"
,
VENDOR_IODATA
,
0x0913
,
PEGASUS_DEV
(
"IO DATA USB ET/TX-S"
,
VENDOR_IODATA
,
0x0913
,
...
...
drivers/usb/net/rtl8150.c
View file @
e1f015ee
...
@@ -113,9 +113,11 @@ static void rtl8150_disconnect(struct usb_interface *intf);
...
@@ -113,9 +113,11 @@ static void rtl8150_disconnect(struct usb_interface *intf);
static
int
rtl8150_probe
(
struct
usb_interface
*
intf
,
static
int
rtl8150_probe
(
struct
usb_interface
*
intf
,
const
struct
usb_device_id
*
id
);
const
struct
usb_device_id
*
id
);
static
const
char
driver_name
[]
=
"rtl8150"
;
static
struct
usb_driver
rtl8150_driver
=
{
static
struct
usb_driver
rtl8150_driver
=
{
.
owner
=
THIS_MODULE
,
.
owner
=
THIS_MODULE
,
.
name
=
"rtl8150"
,
.
name
=
driver_name
,
.
probe
=
rtl8150_probe
,
.
probe
=
rtl8150_probe
,
.
disconnect
=
rtl8150_disconnect
,
.
disconnect
=
rtl8150_disconnect
,
.
id_table
=
rtl8150_table
,
.
id_table
=
rtl8150_table
,
...
@@ -684,7 +686,7 @@ static int rtl8150_ethtool_ioctl(struct net_device *netdev, void *uaddr)
...
@@ -684,7 +686,7 @@ static int rtl8150_ethtool_ioctl(struct net_device *netdev, void *uaddr)
case
ETHTOOL_GDRVINFO
:{
case
ETHTOOL_GDRVINFO
:{
struct
ethtool_drvinfo
info
=
{
ETHTOOL_GDRVINFO
};
struct
ethtool_drvinfo
info
=
{
ETHTOOL_GDRVINFO
};
strncpy
(
info
.
driver
,
DRIVER_DESC
,
ETHTOOL_BUSINFO_LEN
);
strncpy
(
info
.
driver
,
driver_name
,
ETHTOOL_BUSINFO_LEN
);
strncpy
(
info
.
version
,
DRIVER_VERSION
,
ETHTOOL_BUSINFO_LEN
);
strncpy
(
info
.
version
,
DRIVER_VERSION
,
ETHTOOL_BUSINFO_LEN
);
usb_make_path
(
dev
->
udev
,
info
.
bus_info
,
sizeof
info
.
bus_info
);
usb_make_path
(
dev
->
udev
,
info
.
bus_info
,
sizeof
info
.
bus_info
);
if
(
copy_to_user
(
uaddr
,
&
info
,
sizeof
(
info
)))
if
(
copy_to_user
(
uaddr
,
&
info
,
sizeof
(
info
)))
...
...
drivers/usb/storage/transport.c
View file @
e1f015ee
...
@@ -48,6 +48,7 @@
...
@@ -48,6 +48,7 @@
#include <linux/config.h>
#include <linux/config.h>
#include "transport.h"
#include "transport.h"
#include "protocol.h"
#include "protocol.h"
#include "scsiglue.h"
#include "usb.h"
#include "usb.h"
#include "debug.h"
#include "debug.h"
...
@@ -303,6 +304,11 @@ static int interpret_urb_result(struct us_data *us, unsigned int pipe,
...
@@ -303,6 +304,11 @@ static int interpret_urb_result(struct us_data *us, unsigned int pipe,
US_DEBUGP
(
"-- device NAKed
\n
"
);
US_DEBUGP
(
"-- device NAKed
\n
"
);
return
USB_STOR_XFER_ERROR
;
return
USB_STOR_XFER_ERROR
;
/* babble - the device tried to send more than we wanted to read */
case
-
EOVERFLOW
:
US_DEBUGP
(
"-- Babble
\n
"
);
return
USB_STOR_XFER_LONG
;
/* the transfer was cancelled, presumably by an abort */
/* the transfer was cancelled, presumably by an abort */
case
-
ECONNRESET
:
case
-
ECONNRESET
:
US_DEBUGP
(
"-- transfer cancelled
\n
"
);
US_DEBUGP
(
"-- transfer cancelled
\n
"
);
...
@@ -525,6 +531,12 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
...
@@ -525,6 +531,12 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
return
;
return
;
}
}
/* if the transport provided its own sense data, don't auto-sense */
if
(
result
==
USB_STOR_TRANSPORT_NO_SENSE
)
{
srb
->
result
=
SAM_STAT_CHECK_CONDITION
;
return
;
}
/* Determine if we need to auto-sense
/* Determine if we need to auto-sense
*
*
* I normally don't use a flag like this, but it's almost impossible
* I normally don't use a flag like this, but it's almost impossible
...
@@ -764,7 +776,7 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
...
@@ -764,7 +776,7 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
srb
->
request_buffer
,
transfer_length
,
srb
->
request_buffer
,
transfer_length
,
srb
->
use_sg
,
&
srb
->
resid
);
srb
->
use_sg
,
&
srb
->
resid
);
US_DEBUGP
(
"CBI data stage result is 0x%x
\n
"
,
result
);
US_DEBUGP
(
"CBI data stage result is 0x%x
\n
"
,
result
);
if
(
result
==
USB_STOR_XFER_ERROR
)
if
(
result
>
USB_STOR_XFER_STALLED
)
return
USB_STOR_TRANSPORT_ERROR
;
return
USB_STOR_TRANSPORT_ERROR
;
}
}
...
@@ -854,7 +866,7 @@ int usb_stor_CB_transport(Scsi_Cmnd *srb, struct us_data *us)
...
@@ -854,7 +866,7 @@ int usb_stor_CB_transport(Scsi_Cmnd *srb, struct us_data *us)
srb
->
request_buffer
,
transfer_length
,
srb
->
request_buffer
,
transfer_length
,
srb
->
use_sg
,
&
srb
->
resid
);
srb
->
use_sg
,
&
srb
->
resid
);
US_DEBUGP
(
"CB data stage result is 0x%x
\n
"
,
result
);
US_DEBUGP
(
"CB data stage result is 0x%x
\n
"
,
result
);
if
(
result
==
USB_STOR_XFER_ERROR
)
if
(
result
>
USB_STOR_XFER_STALLED
)
return
USB_STOR_TRANSPORT_ERROR
;
return
USB_STOR_TRANSPORT_ERROR
;
}
}
...
@@ -899,6 +911,7 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
...
@@ -899,6 +911,7 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
struct
bulk_cs_wrap
bcs
;
struct
bulk_cs_wrap
bcs
;
unsigned
int
transfer_length
=
srb
->
request_bufflen
;
unsigned
int
transfer_length
=
srb
->
request_bufflen
;
int
result
;
int
result
;
int
fake_sense
=
0
;
/* set up the command wrapper */
/* set up the command wrapper */
bcb
.
Signature
=
cpu_to_le32
(
US_BULK_CB_SIGN
);
bcb
.
Signature
=
cpu_to_le32
(
US_BULK_CB_SIGN
);
...
@@ -936,6 +949,15 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
...
@@ -936,6 +949,15 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
US_DEBUGP
(
"Bulk data transfer result 0x%x
\n
"
,
result
);
US_DEBUGP
(
"Bulk data transfer result 0x%x
\n
"
,
result
);
if
(
result
==
USB_STOR_XFER_ERROR
)
if
(
result
==
USB_STOR_XFER_ERROR
)
return
USB_STOR_TRANSPORT_ERROR
;
return
USB_STOR_TRANSPORT_ERROR
;
/* If the device tried to send back more data than the
* amount requested, the spec requires us to transfer
* the CSW anyway. Since there's no point retrying the
* the command, we'll return fake sense data indicating
* Illegal Request, Invalid Field in CDB.
*/
if
(
result
==
USB_STOR_XFER_LONG
)
fake_sense
=
1
;
}
}
/* See flow chart on pg 15 of the Bulk Only Transport spec for
/* See flow chart on pg 15 of the Bulk Only Transport spec for
...
@@ -975,6 +997,14 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
...
@@ -975,6 +997,14 @@ int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
/* based on the status code, we report good or bad */
/* based on the status code, we report good or bad */
switch
(
bcs
.
Status
)
{
switch
(
bcs
.
Status
)
{
case
US_BULK_STAT_OK
:
case
US_BULK_STAT_OK
:
/* device babbled -- return fake sense data */
if
(
fake_sense
)
{
memcpy
(
srb
->
sense_buffer
,
usb_stor_sense_invalidCDB
,
sizeof
(
usb_stor_sense_invalidCDB
));
return
USB_STOR_TRANSPORT_NO_SENSE
;
}
/* command good -- note that data could be short */
/* command good -- note that data could be short */
return
USB_STOR_TRANSPORT_GOOD
;
return
USB_STOR_TRANSPORT_GOOD
;
...
...
drivers/usb/storage/transport.h
View file @
e1f015ee
...
@@ -122,7 +122,8 @@ struct bulk_cs_wrap {
...
@@ -122,7 +122,8 @@ struct bulk_cs_wrap {
#define USB_STOR_XFER_GOOD 0
/* good transfer */
#define USB_STOR_XFER_GOOD 0
/* good transfer */
#define USB_STOR_XFER_SHORT 1
/* transferred less than expected */
#define USB_STOR_XFER_SHORT 1
/* transferred less than expected */
#define USB_STOR_XFER_STALLED 2
/* endpoint stalled */
#define USB_STOR_XFER_STALLED 2
/* endpoint stalled */
#define USB_STOR_XFER_ERROR 3
/* transfer died in the middle */
#define USB_STOR_XFER_LONG 3
/* device tried to send too much */
#define USB_STOR_XFER_ERROR 4
/* transfer died in the middle */
/*
/*
* Transport return codes
* Transport return codes
...
@@ -130,7 +131,8 @@ struct bulk_cs_wrap {
...
@@ -130,7 +131,8 @@ struct bulk_cs_wrap {
#define USB_STOR_TRANSPORT_GOOD 0
/* Transport good, command good */
#define USB_STOR_TRANSPORT_GOOD 0
/* Transport good, command good */
#define USB_STOR_TRANSPORT_FAILED 1
/* Transport good, command failed */
#define USB_STOR_TRANSPORT_FAILED 1
/* Transport good, command failed */
#define USB_STOR_TRANSPORT_ERROR 2
/* Transport bad (i.e. device dead) */
#define USB_STOR_TRANSPORT_NO_SENSE 2
/* Command failed, no auto-sense */
#define USB_STOR_TRANSPORT_ERROR 3
/* Transport bad (i.e. device dead) */
/*
/*
* We used to have USB_STOR_XFER_ABORTED and USB_STOR_TRANSPORT_ABORTED
* We used to have USB_STOR_XFER_ABORTED and USB_STOR_TRANSPORT_ABORTED
...
...
drivers/usb/storage/usb.c
View file @
e1f015ee
...
@@ -3,10 +3,11 @@
...
@@ -3,10 +3,11 @@
* $Id: usb.c,v 1.75 2002/04/22 03:39:43 mdharm Exp $
* $Id: usb.c,v 1.75 2002/04/22 03:39:43 mdharm Exp $
*
*
* Current development and maintenance by:
* Current development and maintenance by:
* (c) 1999-200
2
Matthew Dharm (mdharm-usb@one-eyed-alien.net)
* (c) 1999-200
3
Matthew Dharm (mdharm-usb@one-eyed-alien.net)
*
*
* Developed with the assistance of:
* Developed with the assistance of:
* (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org)
* (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org)
* (c) 2003 Alan Stern (stern@rowland.harvard.edu)
*
*
* Initial work by:
* Initial work by:
* (c) 1999 Michael Gee (michael@linuxspecific.com)
* (c) 1999 Michael Gee (michael@linuxspecific.com)
...
@@ -297,7 +298,7 @@ static int usb_stor_control_thread(void * __us)
...
@@ -297,7 +298,7 @@ static int usb_stor_control_thread(void * __us)
/*
/*
* This thread doesn't need any user-level access,
* This thread doesn't need any user-level access,
* so get rid of all our resources.
.
* so get rid of all our resources.
*/
*/
daemonize
(
"usb-storage"
);
daemonize
(
"usb-storage"
);
...
@@ -305,9 +306,6 @@ static int usb_stor_control_thread(void * __us)
...
@@ -305,9 +306,6 @@ static int usb_stor_control_thread(void * __us)
unlock_kernel
();
unlock_kernel
();
/* set up for wakeups by new commands */
init_MUTEX_LOCKED
(
&
us
->
sema
);
/* signal that we've started the thread */
/* signal that we've started the thread */
complete
(
&
(
us
->
notify
));
complete
(
&
(
us
->
notify
));
...
@@ -366,17 +364,6 @@ static int usb_stor_control_thread(void * __us)
...
@@ -366,17 +364,6 @@ static int usb_stor_control_thread(void * __us)
us
->
srb
->
result
=
DID_BAD_TARGET
<<
16
;
us
->
srb
->
result
=
DID_BAD_TARGET
<<
16
;
}
}
/* handle requests for EVPD, which most USB devices do
* not support */
else
if
((
us
->
srb
->
cmnd
[
0
]
==
INQUIRY
)
&&
(
us
->
srb
->
cmnd
[
1
]
&
0x1
))
{
US_DEBUGP
(
"Faking INQUIRY command for EVPD
\n
"
);
memcpy
(
us
->
srb
->
sense_buffer
,
usb_stor_sense_invalidCDB
,
sizeof
(
usb_stor_sense_invalidCDB
));
us
->
srb
->
result
=
SAM_STAT_CHECK_CONDITION
;
}
/* Handle those devices which need us to fake
/* Handle those devices which need us to fake
* their inquiry data */
* their inquiry data */
else
if
((
us
->
srb
->
cmnd
[
0
]
==
INQUIRY
)
&&
else
if
((
us
->
srb
->
cmnd
[
0
]
==
INQUIRY
)
&&
...
@@ -432,272 +419,60 @@ static int usb_stor_control_thread(void * __us)
...
@@ -432,272 +419,60 @@ static int usb_stor_control_thread(void * __us)
return
0
;
return
0
;
}
}
/* Set up the URB and the usb_ctrlrequest.
/***********************************************************************
* us->dev_semaphore must already be locked.
* Device probing and disconnecting
* Note that this function assumes that all the data in the us_data
***********************************************************************/
* structure is current.
* Returns non-zero on failure, zero on success
*/
static
int
usb_stor_allocate_urbs
(
struct
us_data
*
us
)
{
/* calculate and store the pipe values */
us
->
send_ctrl_pipe
=
usb_sndctrlpipe
(
us
->
pusb_dev
,
0
);
us
->
recv_ctrl_pipe
=
usb_rcvctrlpipe
(
us
->
pusb_dev
,
0
);
us
->
send_bulk_pipe
=
usb_sndbulkpipe
(
us
->
pusb_dev
,
us
->
ep_out
);
us
->
recv_bulk_pipe
=
usb_rcvbulkpipe
(
us
->
pusb_dev
,
us
->
ep_in
);
us
->
recv_intr_pipe
=
usb_rcvintpipe
(
us
->
pusb_dev
,
us
->
ep_int
);
/* allocate the usb_ctrlrequest for control packets */
US_DEBUGP
(
"Allocating usb_ctrlrequest
\n
"
);
us
->
dr
=
kmalloc
(
sizeof
(
struct
usb_ctrlrequest
),
GFP_NOIO
);
if
(
!
us
->
dr
)
{
US_DEBUGP
(
"allocation failed
\n
"
);
return
1
;
}
/* allocate the URB we're going to use */
US_DEBUGP
(
"Allocating URB
\n
"
);
us
->
current_urb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
if
(
!
us
->
current_urb
)
{
US_DEBUGP
(
"allocation failed
\n
"
);
return
2
;
}
US_DEBUGP
(
"Allocating scatter-gather request block
\n
"
);
us
->
current_sg
=
kmalloc
(
sizeof
(
*
us
->
current_sg
),
GFP_KERNEL
);
if
(
!
us
->
current_sg
)
{
US_DEBUGP
(
"allocation failed
\n
"
);
return
5
;
}
return
0
;
/* success */
}
/* Deallocate the URB, the usb_ctrlrequest, and the IRQ pipe.
/* Get the unusual_devs entries and the string descriptors */
* us->dev_semaphore must already be locked.
static
void
get_device_info
(
struct
us_data
*
us
,
*/
struct
us_unusual_dev
*
unusual_dev
)
static
void
usb_stor_deallocate_urbs
(
struct
us_data
*
us
)
{
{
/* free the scatter-gather request block */
struct
usb_device
*
dev
=
us
->
pusb_dev
;
if
(
us
->
current_sg
)
{
kfree
(
us
->
current_sg
);
us
->
current_sg
=
NULL
;
}
/* free up the main URB for this device */
if
(
us
->
current_urb
)
{
US_DEBUGP
(
"-- releasing main URB
\n
"
);
usb_free_urb
(
us
->
current_urb
);
us
->
current_urb
=
NULL
;
}
/* free the usb_ctrlrequest buffer */
if
(
us
->
dr
)
{
kfree
(
us
->
dr
);
us
->
dr
=
NULL
;
}
/* mark the device as gone */
usb_put_dev
(
us
->
pusb_dev
);
us
->
pusb_dev
=
NULL
;
}
/* Probe to see if a new device is actually a SCSI device */
static
int
storage_probe
(
struct
usb_interface
*
intf
,
const
struct
usb_device_id
*
id
)
{
struct
usb_device
*
dev
=
interface_to_usbdev
(
intf
);
int
ifnum
=
intf
->
altsetting
->
desc
.
bInterfaceNumber
;
int
i
;
const
int
id_index
=
id
-
storage_usb_ids
;
char
mf
[
USB_STOR_STRING_LEN
];
/* manufacturer */
char
prod
[
USB_STOR_STRING_LEN
];
/* product */
char
serial
[
USB_STOR_STRING_LEN
];
/* serial number */
unsigned
int
flags
;
struct
us_unusual_dev
*
unusual_dev
;
struct
us_data
*
us
=
NULL
;
int
result
;
/* these are temporary copies -- we test on these, then put them
* in the us-data structure
*/
struct
usb_endpoint_descriptor
*
ep_in
=
NULL
;
struct
usb_endpoint_descriptor
*
ep_out
=
NULL
;
struct
usb_endpoint_descriptor
*
ep_int
=
NULL
;
u8
subclass
=
0
;
u8
protocol
=
0
;
/* the altsetting on the interface we're probing that matched our
* usb_match_id table
*/
struct
usb_host_interface
*
altsetting
=
intf
[
ifnum
].
altsetting
+
intf
[
ifnum
].
act_altsetting
;
US_DEBUGP
(
"act_altsetting is %d
\n
"
,
intf
[
ifnum
].
act_altsetting
);
/* clear the temporary strings */
memset
(
mf
,
0
,
sizeof
(
mf
));
memset
(
prod
,
0
,
sizeof
(
prod
));
memset
(
serial
,
0
,
sizeof
(
serial
));
/*
* Can we support this device, either because we know about it
* from our unusual device list, or because it advertises that it's
* compliant to the specification?
*
* id_index is calculated in the declaration to be the index number
* of the match from the usb_device_id table, so we can find the
* corresponding entry in the private table.
*/
US_DEBUGP
(
"id_index calculated to be: %d
\n
"
,
id_index
);
US_DEBUGP
(
"Array length appears to be: %d
\n
"
,
sizeof
(
us_unusual_dev_list
)
/
sizeof
(
us_unusual_dev_list
[
0
]));
if
(
id_index
<
sizeof
(
us_unusual_dev_list
)
/
sizeof
(
us_unusual_dev_list
[
0
]))
{
unusual_dev
=
&
us_unusual_dev_list
[
id_index
];
if
(
unusual_dev
->
vendorName
)
if
(
unusual_dev
->
vendorName
)
US_DEBUGP
(
"Vendor: %s
\n
"
,
unusual_dev
->
vendorName
);
US_DEBUGP
(
"Vendor: %s
\n
"
,
unusual_dev
->
vendorName
);
if
(
unusual_dev
->
productName
)
if
(
unusual_dev
->
productName
)
US_DEBUGP
(
"Product: %s
\n
"
,
unusual_dev
->
productName
);
US_DEBUGP
(
"Product: %s
\n
"
,
unusual_dev
->
productName
);
}
else
/* no, we can't support it */
return
-
EIO
;
/* At this point, we know we've got a live one */
US_DEBUGP
(
"USB Mass Storage device detected
\n
"
);
/* Determine subclass and protocol, or copy from the interface */
subclass
=
unusual_dev
->
useProtocol
;
protocol
=
unusual_dev
->
useTransport
;
flags
=
unusual_dev
->
flags
;
/*
/* Store the entries */
* Find the endpoints we need
us
->
unusual_dev
=
unusual_dev
;
* We are expecting a minimum of 2 endpoints - in and out (bulk).
us
->
subclass
=
unusual_dev
->
useProtocol
;
* An optional interrupt is OK (necessary for CBI protocol).
us
->
protocol
=
unusual_dev
->
useTransport
;
* We will ignore any others.
us
->
flags
=
unusual_dev
->
flags
;
*/
for
(
i
=
0
;
i
<
altsetting
->
desc
.
bNumEndpoints
;
i
++
)
{
struct
usb_endpoint_descriptor
*
ep
;
ep
=
&
altsetting
->
endpoint
[
i
].
desc
;
/* is it an BULK endpoint? */
if
((
ep
->
bmAttributes
&
USB_ENDPOINT_XFERTYPE_MASK
)
==
USB_ENDPOINT_XFER_BULK
)
{
/* BULK in or out? */
if
(
ep
->
bEndpointAddress
&
USB_DIR_IN
)
ep_in
=
ep
;
else
ep_out
=
ep
;
}
/* is it an interrupt endpoint? */
else
if
((
ep
->
bmAttributes
&
USB_ENDPOINT_XFERTYPE_MASK
)
==
USB_ENDPOINT_XFER_INT
)
{
ep_int
=
ep
;
}
}
US_DEBUGP
(
"Endpoints: In: 0x%p Out: 0x%p Int: 0x%p (Period %d)
\n
"
,
ep_in
,
ep_out
,
ep_int
,
ep_int
?
ep_int
->
bInterval
:
0
);
#ifdef CONFIG_USB_STORAGE_SDDR09
if
(
protocol
==
US_PR_EUSB_SDDR09
||
protocol
==
US_PR_DPCM_USB
)
{
/* set the configuration -- STALL is an acceptable response here */
result
=
usb_set_configuration
(
dev
,
1
);
US_DEBUGP
(
"Result from usb_set_configuration is %d
\n
"
,
result
);
if
(
result
==
-
EPIPE
)
{
US_DEBUGP
(
"-- stall on control interface
\n
"
);
}
else
if
(
result
!=
0
)
{
/* it's not a stall, but another error -- time to bail */
US_DEBUGP
(
"-- Unknown error. Rejecting device
\n
"
);
return
-
EIO
;
}
}
#endif
/* Do some basic sanity checks, and bail if we find a problem */
if
(
!
ep_in
||
!
ep_out
||
(
protocol
==
US_PR_CBI
&&
!
ep_int
))
{
US_DEBUGP
(
"Endpoint sanity check failed! Rejecting dev.
\n
"
);
return
-
EIO
;
}
/* At this point, we've decided to try to use the device */
usb_get_dev
(
dev
);
/*
fetch the string
s */
/*
Read the device's string descriptor
s */
if
(
dev
->
descriptor
.
iManufacturer
)
if
(
dev
->
descriptor
.
iManufacturer
)
usb_string
(
dev
,
dev
->
descriptor
.
iManufacturer
,
usb_string
(
dev
,
dev
->
descriptor
.
iManufacturer
,
mf
,
sizeof
(
mf
));
us
->
vendor
,
sizeof
(
us
->
vendor
));
if
(
dev
->
descriptor
.
iProduct
)
if
(
dev
->
descriptor
.
iProduct
)
usb_string
(
dev
,
dev
->
descriptor
.
iProduct
,
usb_string
(
dev
,
dev
->
descriptor
.
iProduct
,
prod
,
sizeof
(
prod
));
us
->
product
,
sizeof
(
us
->
product
));
if
(
dev
->
descriptor
.
iSerialNumber
&&
!
(
flags
&
US_FL_IGNORE_SER
))
if
(
dev
->
descriptor
.
iSerialNumber
&&
!
(
us
->
flags
&
US_FL_IGNORE_SER
))
usb_string
(
dev
,
dev
->
descriptor
.
iSerialNumber
,
usb_string
(
dev
,
dev
->
descriptor
.
iSerialNumber
,
serial
,
sizeof
(
serial
));
us
->
serial
,
sizeof
(
us
->
serial
));
/* New device -- allocate memory and initialize */
if
((
us
=
(
struct
us_data
*
)
kmalloc
(
sizeof
(
struct
us_data
),
GFP_KERNEL
))
==
NULL
)
{
printk
(
KERN_WARNING
USB_STORAGE
"Out of memory
\n
"
);
usb_put_dev
(
dev
);
return
-
ENOMEM
;
}
memset
(
us
,
0
,
sizeof
(
struct
us_data
));
/* Initialize the mutexes only when the struct is new */
init_completion
(
&
(
us
->
notify
));
init_MUTEX_LOCKED
(
&
(
us
->
dev_semaphore
));
/* copy over the subclass and protocol data */
us
->
subclass
=
subclass
;
us
->
protocol
=
protocol
;
us
->
flags
=
flags
;
us
->
unusual_dev
=
unusual_dev
;
/* copy over the endpoint data */
/* Use the unusual_dev strings if the device didn't provide them */
us
->
ep_in
=
ep_in
->
bEndpointAddress
&
USB_ENDPOINT_NUMBER_MASK
;
us
->
ep_out
=
ep_out
->
bEndpointAddress
&
USB_ENDPOINT_NUMBER_MASK
;
if
(
ep_int
)
{
us
->
ep_int
=
ep_int
->
bEndpointAddress
&
USB_ENDPOINT_NUMBER_MASK
;
us
->
ep_bInterval
=
ep_int
->
bInterval
;
}
else
us
->
ep_int
=
us
->
ep_bInterval
=
0
;
/* establish the connection to the new device */
us
->
ifnum
=
ifnum
;
us
->
pusb_dev
=
dev
;
/* copy over the identifiying strings */
strncpy
(
us
->
vendor
,
mf
,
USB_STOR_STRING_LEN
);
strncpy
(
us
->
product
,
prod
,
USB_STOR_STRING_LEN
);
strncpy
(
us
->
serial
,
serial
,
USB_STOR_STRING_LEN
);
if
(
strlen
(
us
->
vendor
)
==
0
)
{
if
(
strlen
(
us
->
vendor
)
==
0
)
{
if
(
unusual_dev
->
vendorName
)
if
(
unusual_dev
->
vendorName
)
strncpy
(
us
->
vendor
,
unusual_dev
->
vendorName
,
strncpy
(
us
->
vendor
,
unusual_dev
->
vendorName
,
USB_STOR_STRING_LEN
);
sizeof
(
us
->
vendor
)
-
1
);
else
else
strncpy
(
us
->
vendor
,
"Unknown"
,
strcpy
(
us
->
vendor
,
"Unknown"
);
USB_STOR_STRING_LEN
);
}
}
if
(
strlen
(
us
->
product
)
==
0
)
{
if
(
strlen
(
us
->
product
)
==
0
)
{
if
(
unusual_dev
->
productName
)
if
(
unusual_dev
->
productName
)
strncpy
(
us
->
product
,
unusual_dev
->
productName
,
strncpy
(
us
->
product
,
unusual_dev
->
productName
,
USB_STOR_STRING_LEN
);
sizeof
(
us
->
product
)
-
1
);
else
else
strncpy
(
us
->
product
,
"Unknown"
,
strcpy
(
us
->
product
,
"Unknown"
);
USB_STOR_STRING_LEN
);
}
}
if
(
strlen
(
us
->
serial
)
==
0
)
if
(
strlen
(
us
->
serial
)
==
0
)
strncpy
(
us
->
serial
,
"None"
,
USB_STOR_STRING_LEN
);
strcpy
(
us
->
serial
,
"None"
);
}
/*
/* Get the transport settings */
* Set the handler pointers based on the protocol
static
int
get_transport
(
struct
us_data
*
us
)
* Again, this data is persistent across reattachments
{
*/
switch
(
us
->
protocol
)
{
switch
(
us
->
protocol
)
{
case
US_PR_CB
:
case
US_PR_CB
:
us
->
transport_name
=
"Control/Bulk"
;
us
->
transport_name
=
"Control/Bulk"
;
...
@@ -783,15 +558,19 @@ static int storage_probe(struct usb_interface *intf,
...
@@ -783,15 +558,19 @@ static int storage_probe(struct usb_interface *intf,
#endif
#endif
default:
default:
/* us->transport_name = "Unknown"; */
return
-
EIO
;
goto
BadDevice
;
}
}
US_DEBUGP
(
"Transport: %s
\n
"
,
us
->
transport_name
);
US_DEBUGP
(
"Transport: %s
\n
"
,
us
->
transport_name
);
/* fix for single-lun devices */
/* fix for single-lun devices */
if
(
us
->
flags
&
US_FL_SINGLE_LUN
)
if
(
us
->
flags
&
US_FL_SINGLE_LUN
)
us
->
max_lun
=
0
;
us
->
max_lun
=
0
;
return
0
;
}
/* Get the protocol settings */
static
int
get_protocol
(
struct
us_data
*
us
)
{
switch
(
us
->
subclass
)
{
switch
(
us
->
subclass
)
{
case
US_SC_RBC
:
case
US_SC_RBC
:
us
->
protocol_name
=
"Reduced Block Commands (RBC)"
;
us
->
protocol_name
=
"Reduced Block Commands (RBC)"
;
...
@@ -834,173 +613,335 @@ static int storage_probe(struct usb_interface *intf,
...
@@ -834,173 +613,335 @@ static int storage_probe(struct usb_interface *intf,
#endif
#endif
default:
default:
/* us->protocol_name = "Unknown"; */
return
-
EIO
;
goto
BadDevice
;
}
}
US_DEBUGP
(
"Protocol: %s
\n
"
,
us
->
protocol_name
);
US_DEBUGP
(
"Protocol: %s
\n
"
,
us
->
protocol_name
);
return
0
;
}
/* allocate the URB, the usb_ctrlrequest, and the IRQ URB */
/* Get the pipe settings */
if
(
usb_stor_allocate_urbs
(
us
))
static
int
get_pipes
(
struct
us_data
*
us
)
goto
BadDevice
;
{
struct
usb_host_interface
*
altsetting
=
&
us
->
pusb_intf
->
altsetting
[
us
->
pusb_intf
->
act_altsetting
];
int
i
;
struct
usb_endpoint_descriptor
*
ep
;
struct
usb_endpoint_descriptor
*
ep_in
=
NULL
;
struct
usb_endpoint_descriptor
*
ep_out
=
NULL
;
struct
usb_endpoint_descriptor
*
ep_int
=
NULL
;
/*
* Find the endpoints we need.
* We are expecting a minimum of 2 endpoints - in and out (bulk).
* An optional interrupt is OK (necessary for CBI protocol).
* We will ignore any others.
*/
for
(
i
=
0
;
i
<
altsetting
->
desc
.
bNumEndpoints
;
i
++
)
{
ep
=
&
altsetting
->
endpoint
[
i
].
desc
;
/* Is it a BULK endpoint? */
if
((
ep
->
bmAttributes
&
USB_ENDPOINT_XFERTYPE_MASK
)
==
USB_ENDPOINT_XFER_BULK
)
{
/* BULK in or out? */
if
(
ep
->
bEndpointAddress
&
USB_DIR_IN
)
ep_in
=
ep
;
else
ep_out
=
ep
;
}
/* Is it an interrupt endpoint? */
else
if
((
ep
->
bmAttributes
&
USB_ENDPOINT_XFERTYPE_MASK
)
==
USB_ENDPOINT_XFER_INT
)
{
ep_int
=
ep
;
}
}
US_DEBUGP
(
"Endpoints: In: 0x%p Out: 0x%p Int: 0x%p (Period %d)
\n
"
,
ep_in
,
ep_out
,
ep_int
,
ep_int
?
ep_int
->
bInterval
:
0
);
if
(
!
ep_in
||
!
ep_out
||
(
us
->
protocol
==
US_PR_CBI
&&
!
ep_int
))
{
US_DEBUGP
(
"Endpoint sanity check failed! Rejecting dev.
\n
"
);
return
-
EIO
;
}
/* Calculate and store the pipe values */
us
->
send_ctrl_pipe
=
usb_sndctrlpipe
(
us
->
pusb_dev
,
0
);
us
->
recv_ctrl_pipe
=
usb_rcvctrlpipe
(
us
->
pusb_dev
,
0
);
us
->
send_bulk_pipe
=
usb_sndbulkpipe
(
us
->
pusb_dev
,
ep_out
->
bEndpointAddress
&
USB_ENDPOINT_NUMBER_MASK
);
us
->
recv_bulk_pipe
=
usb_rcvbulkpipe
(
us
->
pusb_dev
,
ep_in
->
bEndpointAddress
&
USB_ENDPOINT_NUMBER_MASK
);
if
(
ep_int
)
{
us
->
recv_intr_pipe
=
usb_rcvintpipe
(
us
->
pusb_dev
,
ep_int
->
bEndpointAddress
&
USB_ENDPOINT_NUMBER_MASK
);
us
->
ep_bInterval
=
ep_int
->
bInterval
;
}
return
0
;
}
/* Initialize all the dynamic resources we need */
static
int
usb_stor_acquire_resources
(
struct
us_data
*
us
)
{
int
p
;
/* Allocate the USB control blocks */
US_DEBUGP
(
"Allocating usb_ctrlrequest
\n
"
);
us
->
dr
=
kmalloc
(
sizeof
(
*
us
->
dr
),
GFP_KERNEL
);
if
(
!
us
->
dr
)
{
US_DEBUGP
(
"allocation failed
\n
"
);
return
-
ENOMEM
;
}
US_DEBUGP
(
"Allocating URB
\n
"
);
us
->
current_urb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
if
(
!
us
->
current_urb
)
{
US_DEBUGP
(
"allocation failed
\n
"
);
return
-
ENOMEM
;
}
US_DEBUGP
(
"Allocating scatter-gather request block
\n
"
);
us
->
current_sg
=
kmalloc
(
sizeof
(
*
us
->
current_sg
),
GFP_KERNEL
);
if
(
!
us
->
current_sg
)
{
US_DEBUGP
(
"allocation failed
\n
"
);
return
-
ENOMEM
;
}
/* Lock the device while we carry out the next two operations */
down
(
&
us
->
dev_semaphore
);
/* For bulk-only devices, determine the max LUN value */
/* For bulk-only devices, determine the max LUN value */
if
(
us
->
protocol
==
US_PR_BULK
)
if
(
us
->
protocol
==
US_PR_BULK
)
us
->
max_lun
=
usb_stor_Bulk_max_lun
(
us
);
us
->
max_lun
=
usb_stor_Bulk_max_lun
(
us
);
/*
* Since this is a new device, we need to generate a scsi
* host definition, and register with the higher SCSI layers
*/
/* Just before we start our control thread, initialize
/* Just before we start our control thread, initialize
* the device if it needs initialization */
* the device if it needs initialization */
if
(
u
nusual_dev
&&
unusual_dev
->
initFunction
)
if
(
u
s
->
unusual_dev
->
initFunction
)
unusual_dev
->
initFunction
(
us
);
u
s
->
u
nusual_dev
->
initFunction
(
us
);
/* start up our control thread */
up
(
&
us
->
dev_semaphore
);
/* Start up our control thread */
atomic_set
(
&
us
->
sm_state
,
US_STATE_IDLE
);
atomic_set
(
&
us
->
sm_state
,
US_STATE_IDLE
);
us
->
pid
=
kernel_thread
(
usb_stor_control_thread
,
us
,
p
=
kernel_thread
(
usb_stor_control_thread
,
us
,
CLONE_VM
);
CLONE_VM
);
if
(
p
<
0
)
{
if
(
us
->
pid
<
0
)
{
printk
(
KERN_WARNING
USB_STORAGE
printk
(
KERN_WARNING
USB_STORAGE
"Unable to start control thread
\n
"
);
"Unable to start control thread
\n
"
);
goto
BadDevice
;
return
p
;
}
}
us
->
pid
=
p
;
/*
w
ait for the thread to start */
/*
W
ait for the thread to start */
wait_for_completion
(
&
(
us
->
notify
));
wait_for_completion
(
&
(
us
->
notify
));
/*
unlock the device pointers */
/*
up
(
&
(
us
->
dev_semaphore
));
* Since this is a new device, we need to register a SCSI
* host definition with the higher SCSI layers.
/* now register
*/
*/
us
->
host
=
scsi_register
(
&
usb_stor_host_template
,
sizeof
(
us
));
us
->
host
=
scsi_register
(
&
usb_stor_host_template
,
sizeof
(
us
));
if
(
!
us
->
host
)
{
if
(
!
us
->
host
)
{
printk
(
KERN_WARNING
USB_STORAGE
printk
(
KERN_WARNING
USB_STORAGE
"Unable to register the scsi host
\n
"
);
"Unable to register the scsi host
\n
"
);
return
-
EBUSY
;
}
/* tell the control thread to exit */
/* Set the hostdata to prepare for scanning */
us
->
srb
=
NULL
;
us
->
host
->
hostdata
[
0
]
=
(
unsigned
long
)
us
;
up
(
&
us
->
sema
);
wait_for_completion
(
&
us
->
notify
);
return
0
;
}
/* re-lock the device pointers */
/* Dissociate from the USB device */
static
void
dissociate_dev
(
struct
us_data
*
us
)
{
US_DEBUGP
(
"-- %s
\n
"
,
__FUNCTION__
);
down
(
&
us
->
dev_semaphore
);
down
(
&
us
->
dev_semaphore
);
usb_set_intfdata
(
us
->
pusb_intf
,
NULL
);
usb_put_dev
(
us
->
pusb_dev
);
us
->
pusb_dev
=
NULL
;
us
->
pusb_intf
=
NULL
;
up
(
&
us
->
dev_semaphore
);
}
/* Release all our static and dynamic resources */
void
usb_stor_release_resources
(
struct
us_data
*
us
)
{
/*
* The host must already have been removed
* and dissociate_dev() must have been called.
*/
/* Finish the SCSI host removal sequence */
if
(
us
->
host
)
{
(
struct
us_data
*
)
us
->
host
->
hostdata
[
0
]
=
NULL
;
scsi_unregister
(
us
->
host
);
}
/* Kill the control thread
*
* Enqueue the command, wake up the thread, and wait for
* notification that it has exited.
*/
if
(
us
->
pid
)
{
US_DEBUGP
(
"-- sending exit command to thread
\n
"
);
BUG_ON
(
atomic_read
(
&
us
->
sm_state
)
!=
US_STATE_IDLE
);
us
->
srb
=
NULL
;
up
(
&
(
us
->
sema
));
wait_for_completion
(
&
(
us
->
notify
));
}
/* Call the destructor routine, if it exists */
if
(
us
->
extra_destructor
)
{
US_DEBUGP
(
"-- calling extra_destructor()
\n
"
);
us
->
extra_destructor
(
us
->
extra
);
}
/* Destroy the extra data */
if
(
us
->
extra
)
{
kfree
(
us
->
extra
);
}
/* Free the USB control blocks */
if
(
us
->
current_sg
)
kfree
(
us
->
current_sg
);
if
(
us
->
current_urb
)
usb_free_urb
(
us
->
current_urb
);
if
(
us
->
dr
)
kfree
(
us
->
dr
);
/* Free the structure itself */
kfree
(
us
);
US_DEBUGP
(
"-- %s finished
\n
"
,
__FUNCTION__
);
}
/* Probe to see if we can drive a newly-connected USB device */
static
int
storage_probe
(
struct
usb_interface
*
intf
,
const
struct
usb_device_id
*
id
)
{
struct
us_data
*
us
;
const
int
id_index
=
id
-
storage_usb_ids
;
int
result
;
US_DEBUGP
(
"USB Mass Storage device detected
\n
"
);
US_DEBUGP
(
"act_altsetting is %d, id_index is %d
\n
"
,
intf
->
act_altsetting
,
id_index
);
/* Allocate the us_data structure and initialize the mutexes */
us
=
(
struct
us_data
*
)
kmalloc
(
sizeof
(
*
us
),
GFP_KERNEL
);
if
(
!
us
)
{
printk
(
KERN_WARNING
USB_STORAGE
"Out of memory
\n
"
);
return
-
ENOMEM
;
}
memset
(
us
,
0
,
sizeof
(
struct
us_data
));
init_MUTEX
(
&
(
us
->
dev_semaphore
));
init_MUTEX_LOCKED
(
&
(
us
->
sema
));
init_completion
(
&
(
us
->
notify
));
/* Fill in the device-related fields */
us
->
pusb_dev
=
interface_to_usbdev
(
intf
);
us
->
pusb_intf
=
intf
;
us
->
ifnum
=
intf
->
altsetting
->
desc
.
bInterfaceNumber
;
/* Store our private data in the interface and increment the
* device's reference count */
usb_set_intfdata
(
intf
,
us
);
usb_get_dev
(
us
->
pusb_dev
);
/*
* Get the unusual_devs entries and the descriptors
*
* id_index is calculated in the declaration to be the index number
* of the match from the usb_device_id table, so we can find the
* corresponding entry in the private table.
*/
get_device_info
(
us
,
&
us_unusual_dev_list
[
id_index
]);
#ifdef CONFIG_USB_STORAGE_SDDR09
if
(
us
->
protocol
==
US_PR_EUSB_SDDR09
||
us
->
protocol
==
US_PR_DPCM_USB
)
{
/* set the configuration -- STALL is an acceptable response here */
result
=
usb_set_configuration
(
us
->
pusb_dev
,
1
);
US_DEBUGP
(
"Result from usb_set_configuration is %d
\n
"
,
result
);
if
(
result
==
-
EPIPE
)
{
US_DEBUGP
(
"-- stall on control interface
\n
"
);
}
else
if
(
result
!=
0
)
{
/* it's not a stall, but another error -- time to bail */
US_DEBUGP
(
"-- Unknown error. Rejecting device
\n
"
);
goto
BadDevice
;
goto
BadDevice
;
}
}
}
#endif
/* set the hostdata to prepare for scanning */
/* Get the transport, protocol, and pipe settings */
us
->
host
->
hostdata
[
0
]
=
(
unsigned
long
)
us
;
result
=
get_transport
(
us
);
if
(
result
)
goto
BadDevice
;
result
=
get_protocol
(
us
);
if
(
result
)
goto
BadDevice
;
result
=
get_pipes
(
us
);
if
(
result
)
goto
BadDevice
;
/* Acquire all the other resources */
result
=
usb_stor_acquire_resources
(
us
);
if
(
result
)
goto
BadDevice
;
/*
now add the host
*/
/*
Finally, add the host (this does SCSI device scanning)
*/
result
=
scsi_add_host
(
us
->
host
,
&
intf
->
dev
);
result
=
scsi_add_host
(
us
->
host
,
&
intf
->
dev
);
if
(
result
)
{
if
(
result
)
{
printk
(
KERN_WARNING
USB_STORAGE
printk
(
KERN_WARNING
USB_STORAGE
"Unable to add the scsi host
\n
"
);
"Unable to add the scsi host
\n
"
);
/* tell the control thread to exit */
us
->
srb
=
NULL
;
up
(
&
us
->
sema
);
wait_for_completion
(
&
us
->
notify
);
/* re-lock the device pointers */
down
(
&
us
->
dev_semaphore
);
goto
BadDevice
;
goto
BadDevice
;
}
}
printk
(
KERN_DEBUG
printk
(
KERN_DEBUG
"WARNING: USB Mass Storage data integrity not assured
\n
"
);
"WARNING: USB Mass Storage data integrity not assured
\n
"
);
printk
(
KERN_DEBUG
printk
(
KERN_DEBUG
"USB Mass Storage device found at %d
\n
"
,
dev
->
devnum
);
"USB Mass Storage device found at %d
\n
"
,
us
->
pusb_dev
->
devnum
);
/* save a pointer to our structure */
usb_set_intfdata
(
intf
,
us
);
return
0
;
return
0
;
/* we come here if there are any problems */
/* We come here if there are any problems */
/* us->dev_semaphore must be locked */
BadDevice:
BadDevice:
US_DEBUGP
(
"storage_probe() failed
\n
"
);
US_DEBUGP
(
"storage_probe() failed
\n
"
);
usb_stor_deallocate_urbs
(
us
);
dissociate_dev
(
us
);
up
(
&
us
->
dev_semaphore
);
usb_stor_release_resources
(
us
);
kfree
(
us
);
return
result
;
return
-
EIO
;
}
}
/* Handle a disconnect event from the USB core */
/* Handle a disconnect event from the USB core */
static
void
storage_disconnect
(
struct
usb_interface
*
intf
)
static
void
storage_disconnect
(
struct
usb_interface
*
intf
)
{
{
struct
us_data
*
us
;
struct
us_data
*
us
=
usb_get_intfdata
(
intf
)
;
struct
scsi_device
*
sdev
;
struct
scsi_device
*
sdev
;
US_DEBUGP
(
"storage_disconnect() called
\n
"
);
US_DEBUGP
(
"storage_disconnect() called
\n
"
);
us
=
usb_get_intfdata
(
intf
);
/* Set devices offline -- need host lock for this */
usb_set_intfdata
(
intf
,
NULL
);
/* set devices offline -- need host lock for this */
scsi_lock
(
us
->
host
);
scsi_lock
(
us
->
host
);
list_for_each_entry
(
sdev
,
&
us
->
host
->
my_devices
,
siblings
)
list_for_each_entry
(
sdev
,
&
us
->
host
->
my_devices
,
siblings
)
sdev
->
online
=
0
;
sdev
->
online
=
0
;
scsi_unlock
(
us
->
host
);
scsi_unlock
(
us
->
host
);
/*
p
revent new USB transfers and stop the current command */
/*
P
revent new USB transfers and stop the current command */
set_bit
(
US_FLIDX_DISCONNECTING
,
&
us
->
flags
);
set_bit
(
US_FLIDX_DISCONNECTING
,
&
us
->
flags
);
usb_stor_stop_transport
(
us
);
usb_stor_stop_transport
(
us
);
/* lock device access -- no need to unlock, as we're going away */
/* Dissociate from the USB device */
down
(
&
(
us
->
dev_semaphore
));
dissociate_dev
(
us
);
/* TODO: somehow, wait for the device to
* be 'idle' (tasklet completion) */
/* remove the pointer to the data structure we were using */
(
struct
us_data
*
)
us
->
host
->
hostdata
[
0
]
=
NULL
;
/*
begin
SCSI host removal sequence */
/*
Begin the
SCSI host removal sequence */
if
(
scsi_remove_host
(
us
->
host
))
{
if
(
scsi_remove_host
(
us
->
host
))
{
US_DEBUGP
(
"-- SCSI refused to
unregister
\n
"
);
US_DEBUGP
(
"-- SCSI refused to
remove the host
\n
"
);
BUG
();
BUG
();
return
;
return
;
};
/* finish SCSI host removal sequence */
scsi_unregister
(
us
->
host
);
/* Kill the control threads
*
* Enqueue the command, wake up the thread, and wait for
* notification that it has exited.
*/
US_DEBUGP
(
"-- sending exit command to thread
\n
"
);
BUG_ON
(
atomic_read
(
&
us
->
sm_state
)
!=
US_STATE_IDLE
);
us
->
srb
=
NULL
;
up
(
&
(
us
->
sema
));
wait_for_completion
(
&
(
us
->
notify
));
/* free allocated urbs */
usb_stor_deallocate_urbs
(
us
);
/* If there's extra data in the us_data structure then
* free that first */
if
(
us
->
extra
)
{
/* call the destructor routine, if it exists */
if
(
us
->
extra_destructor
)
{
US_DEBUGP
(
"-- calling extra_destructor()
\n
"
);
us
->
extra_destructor
(
us
->
extra
);
}
}
/* destroy the extra data */
/* TODO: somehow, wait for the device to
US_DEBUGP
(
"-- freeing the data structure
\n
"
);
* be 'idle' (tasklet completion) */
kfree
(
us
->
extra
);
}
/* up the semaphore so auto-code-checkers won't complain about
* the down/up imbalance */
up
(
&
(
us
->
dev_semaphore
));
/*
free the structure itself
*/
/*
Release all our other resources
*/
kfree
(
us
);
usb_stor_release_resources
(
us
);
}
}
/***********************************************************************
/***********************************************************************
...
...
drivers/usb/storage/usb.h
View file @
e1f015ee
...
@@ -107,6 +107,7 @@ struct us_data {
...
@@ -107,6 +107,7 @@ struct us_data {
*/
*/
struct
semaphore
dev_semaphore
;
/* protect pusb_dev */
struct
semaphore
dev_semaphore
;
/* protect pusb_dev */
struct
usb_device
*
pusb_dev
;
/* this usb_device */
struct
usb_device
*
pusb_dev
;
/* this usb_device */
struct
usb_interface
*
pusb_intf
;
/* this interface */
unsigned
long
flags
;
/* from filter initially */
unsigned
long
flags
;
/* from filter initially */
unsigned
int
send_bulk_pipe
;
/* cached pipe values */
unsigned
int
send_bulk_pipe
;
/* cached pipe values */
unsigned
int
recv_bulk_pipe
;
unsigned
int
recv_bulk_pipe
;
...
@@ -114,7 +115,7 @@ struct us_data {
...
@@ -114,7 +115,7 @@ struct us_data {
unsigned
int
recv_ctrl_pipe
;
unsigned
int
recv_ctrl_pipe
;
unsigned
int
recv_intr_pipe
;
unsigned
int
recv_intr_pipe
;
/* information about the device
-- always good
*/
/* information about the device */
char
vendor
[
USB_STOR_STRING_LEN
];
char
vendor
[
USB_STOR_STRING_LEN
];
char
product
[
USB_STOR_STRING_LEN
];
char
product
[
USB_STOR_STRING_LEN
];
char
serial
[
USB_STOR_STRING_LEN
];
char
serial
[
USB_STOR_STRING_LEN
];
...
@@ -124,11 +125,7 @@ struct us_data {
...
@@ -124,11 +125,7 @@ struct us_data {
u8
protocol
;
u8
protocol
;
u8
max_lun
;
u8
max_lun
;
/* information about the device -- only good if device is attached */
u8
ifnum
;
/* interface number */
u8
ifnum
;
/* interface number */
u8
ep_in
;
/* bulk in endpoint */
u8
ep_out
;
/* bulk out endpoint */
u8
ep_int
;
/* interrupt endpoint */
u8
ep_bInterval
;
/* interrupt interval */
u8
ep_bInterval
;
/* interrupt interval */
/* function pointers for this device */
/* function pointers for this device */
...
...
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