Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
2ef7e8ce
Commit
2ef7e8ce
authored
Feb 04, 2002
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
v2.4.12.4 -> v2.4.12.5
- Greg KH: usbnet fix - Johannes Erdfelt: uhci.c bulk queueing fixes
parent
96c4fbbe
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
205 additions
and
213 deletions
+205
-213
Makefile
Makefile
+1
-1
drivers/char/joystick/analog.c
drivers/char/joystick/analog.c
+4
-2
drivers/usb/uhci.c
drivers/usb/uhci.c
+116
-116
drivers/usb/uhci.h
drivers/usb/uhci.h
+1
-0
drivers/usb/usbnet.c
drivers/usb/usbnet.c
+70
-48
fs/buffer.c
fs/buffer.c
+3
-21
mm/page_alloc.c
mm/page_alloc.c
+1
-1
mm/vmscan.c
mm/vmscan.c
+9
-24
No files found.
Makefile
View file @
2ef7e8ce
VERSION
=
2
PATCHLEVEL
=
4
SUBLEVEL
=
13
EXTRAVERSION
=
-pre
4
EXTRAVERSION
=
-pre
5
KERNELRELEASE
=
$(VERSION)
.
$(PATCHLEVEL)
.
$(SUBLEVEL)$(EXTRAVERSION)
...
...
drivers/char/joystick/analog.c
View file @
2ef7e8ce
...
...
@@ -138,7 +138,7 @@ struct analog_port {
#ifdef __i386__
#define TSC_PRESENT (test_bit(X86_FEATURE_TSC, &boot_cpu_data.x86_capability))
#define GET_TIME(x) do { if (TSC_PRESENT) rdtscl(x); else
outb(0, 0x43); x = inb(0x40); x |= inb(0x40) << 8;
} while (0)
#define GET_TIME(x) do { if (TSC_PRESENT) rdtscl(x); else
{ outb(0, 0x43); x = inb(0x40); x |= inb(0x40) << 8; }
} while (0)
#define DELTA(x,y) (TSC_PRESENT?((y)-(x)):((x)-(y)+((x)<(y)?1193180L/HZ:0)))
#define TIME_NAME (TSC_PRESENT?"TSC":"PIT")
#elif __x86_64__
...
...
@@ -499,7 +499,9 @@ static void analog_init_device(struct analog_port *port, struct analog *analog,
else
printk
(
" [%s timer, %d %sHz clock, %d ns res]
\n
"
,
TIME_NAME
,
port
->
speed
>
10000
?
(
port
->
speed
+
800
)
/
1000
:
port
->
speed
,
port
->
speed
>
10000
?
"M"
:
"k"
,
(
port
->
loop
*
1000000
)
/
port
->
speed
);
port
->
speed
>
10000
?
"M"
:
"k"
,
port
->
speed
>
10000
?
(
port
->
loop
*
1000
)
/
(
port
->
speed
/
1000
)
:
(
port
->
loop
*
1000000
)
/
port
->
speed
);
}
/*
...
...
drivers/usb/uhci.c
View file @
2ef7e8ce
...
...
@@ -113,44 +113,6 @@ static int uhci_alloc_dev(struct usb_device *dev)
static
int
uhci_free_dev
(
struct
usb_device
*
dev
)
{
struct
uhci
*
uhci
=
(
struct
uhci
*
)
dev
->
bus
->
hcpriv
;
struct
list_head
list
,
*
tmp
,
*
head
;
unsigned
long
flags
;
/* Walk through the entire URB list and forcefully remove any */
/* URBs that are still active for that device */
/* Two stage unlink so we don't deadlock on urb_list_lock */
INIT_LIST_HEAD
(
&
list
);
spin_lock_irqsave
(
&
uhci
->
urb_list_lock
,
flags
);
head
=
&
uhci
->
urb_list
;
tmp
=
head
->
next
;
while
(
tmp
!=
head
)
{
struct
urb
*
urb
=
list_entry
(
tmp
,
struct
urb
,
urb_list
);
tmp
=
tmp
->
next
;
if
(
urb
->
dev
==
dev
)
{
list_del
(
&
urb
->
urb_list
);
list_add
(
&
urb
->
urb_list
,
&
list
);
}
}
spin_unlock_irqrestore
(
&
uhci
->
urb_list_lock
,
flags
);
head
=
&
list
;
tmp
=
head
->
next
;
while
(
tmp
!=
head
)
{
struct
urb
*
urb
=
list_entry
(
tmp
,
struct
urb
,
urb_list
);
tmp
=
tmp
->
next
;
/* Make sure we block waiting on these to die */
urb
->
transfer_flags
&=
~
USB_ASYNC_UNLINK
;
/* uhci_unlink_urb will unlink from the temp list */
uhci_unlink_urb
(
urb
);
}
return
0
;
}
...
...
@@ -396,50 +358,96 @@ static void uhci_free_qh(struct uhci *uhci, struct uhci_qh *qh)
pci_pool_free
(
uhci
->
qh_pool
,
qh
,
qh
->
dma_handle
);
}
static
void
uhci_insert_qh
(
struct
uhci
*
uhci
,
struct
uhci_qh
*
skelqh
,
struct
uhci_qh
*
qh
)
static
void
_uhci_insert_qh
(
struct
uhci
*
uhci
,
struct
uhci_qh
*
skelqh
,
struct
urb
*
urb
)
{
struct
urb_priv
*
urbp
=
(
struct
urb_priv
*
)
urb
->
hcpriv
;
struct
list_head
*
head
,
*
tmp
;
struct
uhci_qh
*
lqh
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
uhci
->
frame_list_lock
,
flags
);
/* Grab the last QH */
lqh
=
list_entry
(
skelqh
->
list
.
prev
,
struct
uhci_qh
,
list
);
qh
->
link
=
lqh
->
link
;
if
(
lqh
->
urbp
)
{
head
=
&
lqh
->
urbp
->
queue_list
;
tmp
=
head
->
next
;
while
(
head
!=
tmp
)
{
struct
urb_priv
*
turbp
=
list_entry
(
tmp
,
struct
urb_priv
,
queue_list
);
tmp
=
tmp
->
next
;
turbp
->
qh
->
link
=
urbp
->
qh
->
dma_handle
|
UHCI_PTR_QH
;
}
}
head
=
&
urbp
->
queue_list
;
tmp
=
head
->
next
;
while
(
head
!=
tmp
)
{
struct
urb_priv
*
turbp
=
list_entry
(
tmp
,
struct
urb_priv
,
queue_list
);
tmp
=
tmp
->
next
;
turbp
->
qh
->
link
=
lqh
->
link
;
}
urbp
->
qh
->
link
=
lqh
->
link
;
mb
();
/* Ordering is important */
lqh
->
link
=
qh
->
dma_handle
|
UHCI_PTR_QH
;
lqh
->
link
=
urbp
->
qh
->
dma_handle
|
UHCI_PTR_QH
;
list_add_tail
(
&
urbp
->
qh
->
list
,
&
skelqh
->
list
);
}
list_add_tail
(
&
qh
->
list
,
&
skelqh
->
list
);
static
void
uhci_insert_qh
(
struct
uhci
*
uhci
,
struct
uhci_qh
*
skelqh
,
struct
urb
*
urb
)
{
unsigned
long
flags
;
spin_lock_irqsave
(
&
uhci
->
frame_list_lock
,
flags
);
_uhci_insert_qh
(
uhci
,
skelqh
,
urb
);
spin_unlock_irqrestore
(
&
uhci
->
frame_list_lock
,
flags
);
}
static
void
uhci_remove_qh
(
struct
uhci
*
uhci
,
struct
u
hci_qh
*
qh
)
static
void
uhci_remove_qh
(
struct
uhci
*
uhci
,
struct
u
rb
*
urb
)
{
struct
urb_priv
*
urbp
=
(
struct
urb_priv
*
)
urb
->
hcpriv
;
unsigned
long
flags
;
struct
uhci_qh
*
prevqh
;
struct
uhci_qh
*
qh
=
urbp
->
qh
,
*
pqh
;
if
(
!
qh
)
return
;
/* Only go through the hoops if it's actually linked in */
if
(
list_empty
(
&
qh
->
list
))
{
goto
list
;
}
if
(
!
list_empty
(
&
qh
->
list
))
{
qh
->
urbp
=
NULL
;
qh
->
urbp
=
NULL
;
spin_lock_irqsave
(
&
uhci
->
frame_list_lock
,
flags
)
;
spin_lock_irqsave
(
&
uhci
->
frame_list_lock
,
flags
);
pqh
=
list_entry
(
qh
->
list
.
prev
,
struct
uhci_qh
,
list
);
prevqh
=
list_entry
(
qh
->
list
.
prev
,
struct
uhci_qh
,
list
);
if
(
pqh
->
urbp
)
{
struct
list_head
*
head
,
*
tmp
;
prevqh
->
link
=
qh
->
link
;
mb
();
qh
->
element
=
qh
->
link
=
UHCI_PTR_TERM
;
head
=
&
pqh
->
urbp
->
queue_list
;
tmp
=
head
->
next
;
while
(
head
!=
tmp
)
{
struct
urb_priv
*
turbp
=
list_entry
(
tmp
,
struct
urb_priv
,
queue_list
);
list_del_init
(
&
qh
->
list
)
;
tmp
=
tmp
->
next
;
spin_unlock_irqrestore
(
&
uhci
->
frame_list_lock
,
flags
);
turbp
->
qh
->
link
=
qh
->
link
;
}
}
pqh
->
link
=
qh
->
link
;
mb
();
qh
->
element
=
qh
->
link
=
UHCI_PTR_TERM
;
list_del_init
(
&
qh
->
list
);
spin_unlock_irqrestore
(
&
uhci
->
frame_list_lock
,
flags
);
}
list:
spin_lock_irqsave
(
&
uhci
->
qh_remove_list_lock
,
flags
);
/* Check to see if the remove list is empty. Set the IOC bit */
...
...
@@ -464,9 +472,10 @@ static int uhci_fixup_toggle(struct urb *urb, unsigned int toggle)
tmp
=
tmp
->
next
;
td
->
info
&=
~
(
1
<<
TD_TOKEN_TOGGLE
);
if
(
toggle
)
td
->
info
|=
(
1
<<
TD_TOKEN_TOGGLE
);
set_bit
(
TD_TOKEN_TOGGLE
,
&
td
->
info
);
else
clear_bit
(
TD_TOKEN_TOGGLE
,
&
td
->
info
);
toggle
^=
1
;
}
...
...
@@ -481,7 +490,7 @@ static void uhci_append_queued_urb(struct uhci *uhci, struct urb *eurb, struct u
{
struct
urb_priv
*
eurbp
,
*
urbp
,
*
furbp
,
*
lurbp
;
struct
list_head
*
tmp
;
struct
uhci_td
*
ftd
,
*
lltd
;
struct
uhci_td
*
lltd
;
unsigned
long
flags
;
eurbp
=
eurb
->
hcpriv
;
...
...
@@ -510,13 +519,15 @@ static void uhci_append_queued_urb(struct uhci *uhci, struct urb *eurb, struct u
lurbp
=
list_entry
(
furbp
->
queue_list
.
prev
,
struct
urb_priv
,
queue_list
);
lltd
=
list_entry
(
lurbp
->
td_list
.
prev
,
struct
uhci_td
,
list
);
ftd
=
list_entry
(
urbp
->
td_list
.
next
,
struct
uhci_td
,
list
);
uhci_fixup_toggle
(
urb
,
uhci_toggle
(
lltd
->
info
)
^
1
);
/* All qh's in the queue need to link to the next queue */
urbp
->
qh
->
link
=
eurbp
->
qh
->
link
;
mb
();
/* Make sure we flush everything */
/* Only support bulk right now, so no depth */
lltd
->
link
=
ftd
->
dma_handle
;
lltd
->
link
=
urbp
->
qh
->
dma_handle
|
UHCI_PTR_QH
;
list_add_tail
(
&
urbp
->
queue_list
,
&
furbp
->
queue_list
);
...
...
@@ -576,30 +587,9 @@ static void uhci_delete_queued_urb(struct uhci *uhci, struct urb *urb)
usb_pipeout
(
urb
->
pipe
),
toggle
);
if
(
!
urbp
->
queued
)
{
int
status
;
/* The HC may continue using the current QH if it finished */
/* all of the TD's in this URB and may have started on the */
/* next URB's TD's already, so we'll take over ownership */
/* of this QH and use it instead. Don't forget to delete */
/* the old QH first */
uhci_free_qh
(
uhci
,
nurbp
->
qh
);
nurbp
->
qh
=
urbp
->
qh
;
nurbp
->
qh
->
urbp
=
nurbp
;
urbp
->
qh
=
NULL
;
/* If the last TD from the first (this) urb didn't */
/* complete, reset qh->element to the first TD in the */
/* next urb */
pltd
=
list_entry
(
urbp
->
td_list
.
prev
,
struct
uhci_td
,
list
);
status
=
uhci_status_bits
(
pltd
->
status
);
if
((
status
&
TD_CTRL_ACTIVE
)
||
uhci_actual_length
(
pltd
->
status
)
<
uhci_expected_length
(
pltd
->
info
))
{
struct
uhci_td
*
ftd
=
list_entry
(
nurbp
->
td_list
.
next
,
struct
uhci_td
,
list
);
nurbp
->
qh
->
element
=
ftd
->
dma_handle
;
}
nurbp
->
queued
=
0
;
_uhci_insert_qh
(
uhci
,
uhci
->
skel_bulk_qh
,
nurbp
->
urb
);
}
else
{
/* We're somewhere in the middle (or end). A bit trickier */
/* than the head scenario */
...
...
@@ -607,15 +597,10 @@ static void uhci_delete_queued_urb(struct uhci *uhci, struct urb *urb)
queue_list
);
pltd
=
list_entry
(
purbp
->
td_list
.
prev
,
struct
uhci_td
,
list
);
if
(
nurbp
->
queued
)
{
struct
uhci_td
*
nftd
;
/* Close the gap between the two */
nftd
=
list_entry
(
nurbp
->
td_list
.
next
,
struct
uhci_td
,
list
);
pltd
->
link
=
nftd
->
dma_handle
;
}
else
/* The next URB happens to be the beggining, so */
if
(
nurbp
->
queued
)
pltd
->
link
=
nurbp
->
qh
->
dma_handle
|
UHCI_PTR_QH
;
else
/* The next URB happens to be the beginning, so */
/* we're the last, end the chain */
pltd
->
link
=
UHCI_PTR_TERM
;
}
...
...
@@ -639,6 +624,7 @@ static struct urb_priv *uhci_alloc_urb_priv(struct uhci *uhci, struct urb *urb)
memset
((
void
*
)
urbp
,
0
,
sizeof
(
*
urbp
));
urbp
->
inserttime
=
jiffies
;
urbp
->
fsbrtime
=
jiffies
;
urbp
->
urb
=
urb
;
urbp
->
dev
=
urb
->
dev
;
...
...
@@ -900,19 +886,19 @@ static int uhci_submit_control(struct urb *urb)
if
(
!
qh
)
return
-
ENOMEM
;
urbp
->
qh
=
qh
;
qh
->
urbp
=
urbp
;
/* Low speed or small transfers gets a different queue and treatment */
if
(
urb
->
pipe
&
TD_CTRL_LS
)
{
uhci_insert_tds_in_qh
(
qh
,
urb
,
0
);
uhci_insert_qh
(
uhci
,
uhci
->
skel_ls_control_qh
,
qh
);
uhci_insert_qh
(
uhci
,
uhci
->
skel_ls_control_qh
,
urb
);
}
else
{
uhci_insert_tds_in_qh
(
qh
,
urb
,
1
);
uhci_insert_qh
(
uhci
,
uhci
->
skel_hs_control_qh
,
qh
);
uhci_insert_qh
(
uhci
,
uhci
->
skel_hs_control_qh
,
urb
);
uhci_inc_fsbr
(
uhci
,
urb
);
}
urbp
->
qh
=
qh
;
qh
->
urbp
=
urbp
;
return
-
EINPROGRESS
;
}
...
...
@@ -961,6 +947,7 @@ static int uhci_result_control(struct urb *urb)
!
(
td
->
status
&
TD_CTRL_ACTIVE
))
{
uhci_inc_fsbr
(
urb
->
dev
->
bus
->
hcpriv
,
urb
);
urbp
->
fsbr_timeout
=
0
;
urbp
->
fsbrtime
=
jiffies
;
clear_bit
(
TD_CTRL_IOC_BIT
,
&
td
->
status
);
}
...
...
@@ -1043,7 +1030,7 @@ static int usb_control_retrigger_status(struct urb *urb)
urbp
->
short_control_packet
=
1
;
/* Create a new QH to avoid pointer overwriting problems */
uhci_remove_qh
(
uhci
,
urb
p
->
qh
);
uhci_remove_qh
(
uhci
,
urb
);
/* Delete all of the TD's except for the status TD at the end */
head
=
&
urbp
->
td_list
;
...
...
@@ -1071,9 +1058,9 @@ static int usb_control_retrigger_status(struct urb *urb)
/* Low speed or small transfers gets a different queue and treatment */
if
(
urb
->
pipe
&
TD_CTRL_LS
)
uhci_insert_qh
(
uhci
,
uhci
->
skel_ls_control_qh
,
urb
p
->
qh
);
uhci_insert_qh
(
uhci
,
uhci
->
skel_ls_control_qh
,
urb
);
else
uhci_insert_qh
(
uhci
,
uhci
->
skel_hs_control_qh
,
urb
p
->
qh
);
uhci_insert_qh
(
uhci
,
uhci
->
skel_hs_control_qh
,
urb
);
return
-
EINPROGRESS
;
}
...
...
@@ -1134,6 +1121,7 @@ static int uhci_result_interrupt(struct urb *urb)
!
(
td
->
status
&
TD_CTRL_ACTIVE
))
{
uhci_inc_fsbr
(
urb
->
dev
->
bus
->
hcpriv
,
urb
);
urbp
->
fsbr_timeout
=
0
;
urbp
->
fsbrtime
=
jiffies
;
clear_bit
(
TD_CTRL_IOC_BIT
,
&
td
->
status
);
}
...
...
@@ -1147,10 +1135,6 @@ static int uhci_result_interrupt(struct urb *urb)
goto
td_error
;
if
(
uhci_actual_length
(
td
->
status
)
<
uhci_expected_length
(
td
->
info
))
{
usb_settoggle
(
urb
->
dev
,
uhci_endpoint
(
td
->
info
),
uhci_packetout
(
td
->
info
),
uhci_toggle
(
td
->
info
)
^
1
);
if
(
urb
->
transfer_flags
&
USB_DISABLE_SPD
)
{
ret
=
-
EREMOTEIO
;
goto
err
;
...
...
@@ -1303,7 +1287,7 @@ static int uhci_submit_bulk(struct urb *urb, struct urb *eurb)
if
(
urb
->
transfer_flags
&
USB_QUEUE_BULK
&&
eurb
)
uhci_append_queued_urb
(
uhci
,
eurb
,
urb
);
else
uhci_insert_qh
(
uhci
,
uhci
->
skel_bulk_qh
,
qh
);
uhci_insert_qh
(
uhci
,
uhci
->
skel_bulk_qh
,
urb
);
uhci_inc_fsbr
(
uhci
,
urb
);
...
...
@@ -1681,6 +1665,7 @@ static void uhci_transfer_result(struct uhci *uhci, struct urb *urb)
static
void
uhci_unlink_generic
(
struct
uhci
*
uhci
,
struct
urb
*
urb
)
{
struct
list_head
*
head
,
*
tmp
;
struct
urb_priv
*
urbp
=
urb
->
hcpriv
;
/* We can get called when urbp allocation fails, so check */
...
...
@@ -1689,15 +1674,30 @@ static void uhci_unlink_generic(struct uhci *uhci, struct urb *urb)
uhci_dec_fsbr
(
uhci
,
urb
);
/* Safe since it checks */
head
=
&
urbp
->
td_list
;
tmp
=
head
->
next
;
while
(
tmp
!=
head
)
{
struct
uhci_td
*
td
=
list_entry
(
tmp
,
struct
uhci_td
,
list
);
tmp
=
tmp
->
next
;
/* Control and Isochronous ignore the toggle, so this */
/* is safe for all types */
if
(
!
(
td
->
status
&
TD_CTRL_ACTIVE
)
&&
uhci_actual_length
(
td
->
status
)
<
uhci_expected_length
(
td
->
info
)
||
tmp
==
head
)
{
usb_settoggle
(
urb
->
dev
,
uhci_endpoint
(
td
->
info
),
uhci_packetout
(
td
->
info
),
uhci_toggle
(
td
->
info
)
^
1
);
}
}
uhci_delete_queued_urb
(
uhci
,
urb
);
if
(
urbp
->
qh
)
/* The interrupt loop will reclaim the QH's */
uhci_remove_qh
(
uhci
,
urbp
->
qh
);
/* The interrupt loop will reclaim the QH's */
uhci_remove_qh
(
uhci
,
urb
);
}
/* FIXME: If we forcefully unlink an urb, we should reset the toggle for */
/* that pipe to match what actually completed */
static
int
uhci_unlink_urb
(
struct
urb
*
urb
)
{
struct
uhci
*
uhci
;
...
...
@@ -1951,11 +1951,11 @@ static void rh_int_timer_do(unsigned long ptr)
tmp
=
tmp
->
next
;
/* Check if the FSBR timed out */
if
(
urbp
->
fsbr
&&
time_after_eq
(
jiffies
,
urbp
->
insert
time
+
IDLE_TIMEOUT
))
if
(
urbp
->
fsbr
&&
!
urbp
->
fsbr_timeout
&&
time_after_eq
(
jiffies
,
urbp
->
fsbr
time
+
IDLE_TIMEOUT
))
uhci_fsbr_timeout
(
uhci
,
u
);
/* Check if the URB timed out */
if
(
u
->
timeout
&&
time_after_eq
(
jiffies
,
u
->
timeout
))
{
if
(
u
->
timeout
&&
time_after_eq
(
jiffies
,
u
rbp
->
inserttime
+
u
->
timeout
))
{
list_del
(
&
u
->
urb_list
);
list_add_tail
(
&
u
->
urb_list
,
&
list
);
}
...
...
drivers/usb/uhci.h
View file @
2ef7e8ce
...
...
@@ -345,6 +345,7 @@ struct urb_priv {
int
status
;
/* Final status */
unsigned
long
inserttime
;
/* In jiffies */
unsigned
long
fsbrtime
;
/* In jiffies */
struct
list_head
queue_list
;
struct
list_head
complete_list
;
...
...
drivers/usb/usbnet.c
View file @
2ef7e8ce
...
...
@@ -15,7 +15,7 @@
* support as appropriate. Devices currently supported include:
*
* - AnchorChip 2720
* - Belkin
F5U104 (custom
)
* - Belkin
, eTEK (interops with Win32 drivers
)
* - "Linux Devices" (like iPaq and similar SA-1100 based PDAs)
* - NetChip 1080 (interoperates with NetChip Win32 drivers)
* - Prolific PL-2301/2302 (replaces "plusb" driver)
...
...
@@ -73,6 +73,9 @@
* Win32 Belkin driver; other cleanups (db).
* 16-jul-2001 Bugfixes for uhci oops-on-unplug, Belkin support, various
* cleanups for problems not yet seen in the field. (db)
* 17-oct-2001 Handle "Advance USBNET" product, like Belkin/eTEK devices,
* from Ioannis Mavroukakis <i.mavroukakis@btinternet.com>;
* rx unlinks somehow weren't async; minor cleanup.
*
*-------------------------------------------------------------------------*/
...
...
@@ -97,7 +100,7 @@
#define CONFIG_USB_AN2720
#define CONFIG_USB_BELKIN
_F5U104
#define CONFIG_USB_BELKIN
#define CONFIG_USB_LINUXDEV
#define CONFIG_USB_NET1080
#define CONFIG_USB_PL2301
...
...
@@ -119,7 +122,7 @@
#endif
// packets are always ethernet inside
// ... except they can be bigger (
up to 64K with this
framing)
// ... except they can be bigger (
limit of 64K with NetChip
framing)
#define MIN_PACKET sizeof(struct ethhdr)
#define MAX_PACKET 32768
...
...
@@ -161,7 +164,7 @@ struct usbnet {
struct
sk_buff_head
txq
;
struct
sk_buff_head
done
;
struct
tasklet_struct
bh
;
struct
tq_struct
ctrl_task
;
struct
tq_struct
ctrl_task
;
};
// device-specific info used by the driver
...
...
@@ -169,7 +172,8 @@ struct driver_info {
char
*
description
;
int
flags
;
#define FLAG_FRAMING 0x0001
/* guard against device dropouts */
#define FLAG_FRAMING_NC 0x0001
/* guard against device dropouts */
#define FLAG_NO_SETINT 0x0010
/* device can't set_interface() */
/* reset device ... can sleep */
int
(
*
reset
)(
struct
usbnet
*
);
...
...
@@ -251,7 +255,7 @@ struct nc_trailer {
u16
packet_id
;
}
__attribute__
((
__packed__
));
// packets may use FLAG_FRAMING and optional pad
// packets may use FLAG_FRAMING
_NC
and optional pad
#define FRAMED_SIZE(mtu) (sizeof (struct nc_header) \
+ sizeof (struct ethhdr) \
+ (mtu) \
...
...
@@ -288,22 +292,24 @@ static const struct driver_info an2720_info = {
#ifdef CONFIG_USB_BELKIN
_F5U104
#ifdef CONFIG_USB_BELKIN
/*-------------------------------------------------------------------------
*
* Belkin F5U104 ... two NetChip 2280 devices + Atmel microcontroller
*
* ... also two eTEK designs, including one sold as "Advance USBNET"
*
*-------------------------------------------------------------------------*/
static
const
struct
driver_info
belkin_info
=
{
description:
"Belkin
USB Direct Connect (F5U104)
"
,
description:
"Belkin
, eTEK, or compatible
"
,
in:
1
,
out
:
1
,
// direction distinguishes these
epsize:
64
,
};
#endif
/* CONFIG_USB_BELKIN
_F5U104
*/
#endif
/* CONFIG_USB_BELKIN */
...
...
@@ -632,7 +638,7 @@ static int net1080_check_connect (struct usbnet *dev)
static
const
struct
driver_info
net1080_info
=
{
description:
"NetChip TurboCONNECT"
,
flags:
FLAG_FRAMING
,
flags:
FLAG_FRAMING
_NC
,
reset:
net1080_reset
,
check_connect:
net1080_check_connect
,
...
...
@@ -729,9 +735,9 @@ static int usbnet_change_mtu (struct net_device *net, int new_mtu)
{
struct
usbnet
*
dev
=
(
struct
usbnet
*
)
net
->
priv
;
if
(
new_mtu
<=
sizeof
(
struct
ethhdr
)
||
new_mtu
>
MAX_PACKET
)
if
(
new_mtu
<=
MIN_PACKET
||
new_mtu
>
MAX_PACKET
)
return
-
EINVAL
;
if
(((
dev
->
driver_info
->
flags
)
&
FLAG_FRAMING
))
{
if
(((
dev
->
driver_info
->
flags
)
&
FLAG_FRAMING
_NC
))
{
if
(
FRAMED_SIZE
(
new_mtu
)
>
MAX_PACKET
)
return
-
EINVAL
;
// no second zero-length packet read wanted after mtu-sized packets
...
...
@@ -779,9 +785,11 @@ static void rx_submit (struct usbnet *dev, struct urb *urb, int flags)
unsigned
long
lockflags
;
size_t
size
;
size
=
(
dev
->
driver_info
->
flags
&
FLAG_FRAMING
)
?
FRAMED_SIZE
(
dev
->
net
.
mtu
)
:
(
sizeof
(
struct
ethhdr
)
+
dev
->
net
.
mtu
);
if
(
dev
->
driver_info
->
flags
&
FLAG_FRAMING_NC
)
size
=
FRAMED_SIZE
(
dev
->
net
.
mtu
);
else
size
=
(
sizeof
(
struct
ethhdr
)
+
dev
->
net
.
mtu
);
if
((
skb
=
alloc_skb
(
size
,
flags
))
==
0
)
{
dbg
(
"no rx skb"
);
tasklet_schedule
(
&
dev
->
bh
);
...
...
@@ -798,9 +806,15 @@ static void rx_submit (struct usbnet *dev, struct urb *urb, int flags)
FILL_BULK_URB
(
urb
,
dev
->
udev
,
usb_rcvbulkpipe
(
dev
->
udev
,
dev
->
driver_info
->
in
),
skb
->
data
,
size
,
rx_complete
,
skb
);
urb
->
transfer_flags
|=
USB_ASYNC_UNLINK
;
#ifdef REALLY_QUEUE
urb
->
transfer_flags
|=
USB_QUEUE_BULK
;
#endif
#if 0
// Idle-but-posted reads with UHCI really chew up
// PCI bandwidth unless FSBR is disabled
urb->transfer_flags |= USB_NO_FSBR;
#endif
spin_lock_irqsave
(
&
dev
->
rxq
.
lock
,
lockflags
);
...
...
@@ -827,7 +841,7 @@ static void rx_submit (struct usbnet *dev, struct urb *urb, int flags)
static
inline
void
rx_process
(
struct
usbnet
*
dev
,
struct
sk_buff
*
skb
)
{
if
(
dev
->
driver_info
->
flags
&
FLAG_FRAMING
)
{
if
(
dev
->
driver_info
->
flags
&
FLAG_FRAMING
_NC
)
{
struct
nc_header
*
header
;
struct
nc_trailer
*
trailer
;
...
...
@@ -1083,9 +1097,11 @@ static int usbnet_open (struct net_device *net)
}
netif_start_queue
(
net
);
devdbg
(
dev
,
"open: enable queueing (rx %d, tx %d) mtu %d %s
framed
"
,
devdbg
(
dev
,
"open: enable queueing (rx %d, tx %d) mtu %d %s
framing
"
,
RX_QLEN
,
TX_QLEN
,
dev
->
net
.
mtu
,
(
info
->
flags
&
FLAG_FRAMING
)
?
""
:
"un"
(
info
->
flags
&
FLAG_FRAMING_NC
)
?
"NetChip"
:
"raw"
);
// delay posting reads until we're fully open
...
...
@@ -1194,7 +1210,7 @@ static int usbnet_start_xmit (struct sk_buff *skb, struct net_device *net)
flags
=
in_interrupt
()
?
GFP_ATOMIC
:
GFP_KERNEL
;
if
(
info
->
flags
&
FLAG_FRAMING
)
{
if
(
info
->
flags
&
FLAG_FRAMING
_NC
)
{
struct
sk_buff
*
skb2
;
skb2
=
fixup_skb
(
skb
,
flags
);
if
(
!
skb2
)
{
...
...
@@ -1215,7 +1231,7 @@ static int usbnet_start_xmit (struct sk_buff *skb, struct net_device *net)
entry
->
state
=
tx_start
;
entry
->
length
=
length
;
if
(
info
->
flags
&
FLAG_FRAMING
)
{
if
(
info
->
flags
&
FLAG_FRAMING
_NC
)
{
header
=
(
struct
nc_header
*
)
skb_push
(
skb
,
sizeof
*
header
);
header
->
hdr_len
=
cpu_to_le16
(
sizeof
(
*
header
));
header
->
packet_len
=
cpu_to_le16
(
length
);
...
...
@@ -1223,31 +1239,31 @@ static int usbnet_start_xmit (struct sk_buff *skb, struct net_device *net)
*
skb_put
(
skb
,
1
)
=
PAD_BYTE
;
trailer
=
(
struct
nc_trailer
*
)
skb_put
(
skb
,
sizeof
*
trailer
);
}
else
if
((
length
%
EP_SIZE
(
dev
))
==
0
)
{
if
(
skb_shared
(
skb
))
{
struct
sk_buff
*
skb2
;
skb2
=
skb_unshare
(
skb
,
flags
);
if
(
!
skb2
)
{
dbg
(
"can't unshare skb"
);
goto
drop
;
}
skb
=
skb2
;
// not all hardware behaves with USB_ZERO_PACKET,
// so we add an extra one-byte packet
if
(
skb_shared
(
skb
))
{
struct
sk_buff
*
skb2
;
skb2
=
skb_unshare
(
skb
,
flags
);
if
(
!
skb2
)
{
dbg
(
"can't unshare skb"
);
goto
drop
;
}
skb
->
len
++
;
skb
=
skb2
;
}
skb
->
len
++
;
}
FILL_BULK_URB
(
urb
,
dev
->
udev
,
usb_sndbulkpipe
(
dev
->
udev
,
info
->
out
),
skb
->
data
,
skb
->
len
,
tx_complete
,
skb
);
// Idle-but-posted reads with UHCI really chew up
// PCI bandwidth unless FSBR is disabled
urb
->
transfer_flags
|=
USB_ASYNC_UNLINK
|
USB_NO_FSBR
;
urb
->
transfer_flags
|=
USB_ASYNC_UNLINK
;
#ifdef REALLY_QUEUE
urb
->
transfer_flags
|=
USB_QUEUE_BULK
;
#endif
// FIXME urb->timeout = ... jiffies ... ;
spin_lock_irqsave
(
&
dev
->
txq
.
lock
,
flags
);
if
(
info
->
flags
&
FLAG_FRAMING
)
{
if
(
info
->
flags
&
FLAG_FRAMING
_NC
)
{
header
->
packet_id
=
cpu_to_le16
(
dev
->
packet_id
++
);
put_unaligned
(
header
->
packet_id
,
&
trailer
->
packet_id
);
#if 0
...
...
@@ -1408,9 +1424,12 @@ usbnet_probe (struct usb_device *udev, unsigned ifnum,
return
0
;
}
if
(
usb_set_interface
(
udev
,
ifnum
,
altnum
)
<
0
)
{
err
(
"set_interface failed"
);
return
0
;
// more sanity (unless the device is broken)
if
(
!
(
info
->
flags
&
FLAG_NO_SETINT
))
{
if
(
usb_set_interface
(
udev
,
ifnum
,
altnum
)
<
0
)
{
err
(
"set_interface failed"
);
return
0
;
}
}
// set up our own records
...
...
@@ -1484,6 +1503,18 @@ static const struct usb_device_id products [] = {
},
#endif
#ifdef CONFIG_USB_BELKIN
{
USB_DEVICE
(
0x050d
,
0x0004
),
// Belkin
driver_info:
(
unsigned
long
)
&
belkin_info
,
},
{
USB_DEVICE
(
0x056c
,
0x8100
),
// eTEK
driver_info:
(
unsigned
long
)
&
belkin_info
,
},
{
USB_DEVICE
(
0x0525
,
0x9901
),
// Advance USBNET (eTEK)
driver_info:
(
unsigned
long
)
&
belkin_info
,
},
#endif
// GeneSys GL620USB (www.genesyslogic.com.tw)
// (patch exists against an older driver version)
...
...
@@ -1508,16 +1539,6 @@ static const struct usb_device_id products [] = {
},
#endif
#ifdef CONFIG_USB_BELKIN_F5U104
{
USB_DEVICE
(
0x050d
,
0x0004
),
// Belkin
driver_info:
(
unsigned
long
)
&
belkin_info
,
},
{
USB_DEVICE
(
0x056c
,
0x8100
),
// eTEK
driver_info:
(
unsigned
long
)
&
belkin_info
,
},
#endif
#ifdef CONFIG_USB_PL2301
{
USB_DEVICE
(
0x067b
,
0x0000
),
// PL-2301
...
...
@@ -1563,6 +1584,7 @@ static void __exit usbnet_exit (void)
}
module_exit
(
usbnet_exit
);
EXPORT_NO_SYMBOLS
;
MODULE_AUTHOR
(
"David Brownell <dbrownell@users.sourceforge.net>"
);
MODULE_DESCRIPTION
(
"USB Host-to-Host Link Drivers (
Belkin, Linux, NetChip, Prolific, ...
)"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_DESCRIPTION
(
"USB Host-to-Host Link Drivers (
numerous vendors
)"
);
MODULE_LICENSE
(
"GPL"
);
fs/buffer.c
View file @
2ef7e8ce
...
...
@@ -1131,31 +1131,13 @@ void __brelse(struct buffer_head * buf)
}
/*
* bforget() is like brelse(), except it
might discard
any
* bforget() is like brelse(), except it
discards
any
* potentially dirty data.
*/
void
__bforget
(
struct
buffer_head
*
buf
)
{
/* grab the lru lock here so that "b_count" is stable */
spin_lock
(
&
lru_list_lock
);
write_lock
(
&
hash_table_lock
);
if
(
!
atomic_dec_and_test
(
&
buf
->
b_count
)
||
buffer_locked
(
buf
))
goto
in_use
;
/* Mark it clean */
clear_bit
(
BH_Dirty
,
&
buf
->
b_state
);
write_unlock
(
&
hash_table_lock
);
/* After which we can remove it from all queues */
remove_inode_queue
(
buf
);
__remove_from_lru_list
(
buf
);
buf
->
b_list
=
BUF_CLEAN
;
spin_unlock
(
&
lru_list_lock
);
return
;
in_use:
write_unlock
(
&
hash_table_lock
);
spin_unlock
(
&
lru_list_lock
);
mark_buffer_clean
(
buf
);
__brelse
(
buf
);
}
/**
...
...
mm/page_alloc.c
View file @
2ef7e8ce
...
...
@@ -394,7 +394,7 @@ struct page * __alloc_pages(unsigned int gfp_mask, unsigned int order, zonelist_
}
/* Don't let big-order allocations loop */
if
(
order
)
if
(
order
>
1
)
return
NULL
;
/* Yield for kswapd, and try again */
...
...
mm/vmscan.c
View file @
2ef7e8ce
...
...
@@ -346,11 +346,7 @@ static int shrink_cache(int nr_pages, int max_scan, unsigned int gfp_mask)
page
=
list_entry
(
entry
,
struct
page
,
lru
);
if
(
unlikely
(
!
PageInactive
(
page
)
&&
!
PageActive
(
page
)))
BUG
();
/* Mapping-less page on LRU-list? */
if
(
unlikely
(
!
page
->
mapping
))
if
(
unlikely
(
!
PageInactive
(
page
)))
BUG
();
list_del
(
entry
);
...
...
@@ -363,31 +359,17 @@ static int shrink_cache(int nr_pages, int max_scan, unsigned int gfp_mask)
continue
;
/* Racy check to avoid trylocking when not worthwhile */
if
(
!
is_page_cache_freeable
(
page
))
continue
;
if
(
unlikely
(
TryLockPage
(
page
)))
{
if
(
gfp_mask
&
__GFP_FS
)
{
page_cache_get
(
page
);
spin_unlock
(
&
pagemap_lru_lock
);
wait_on_page
(
page
);
page_cache_release
(
page
);
spin_lock
(
&
pagemap_lru_lock
);
}
if
(
!
page
->
buffers
&&
page_count
(
page
)
!=
1
)
continue
;
}
/*
* Still strictly racy - we don't own the pagecache lock,
* so somebody might look up the page while we do this.
* It's just a heuristic, though.
* The page is locked. IO in progress?
* Move it to the back of the list.
*/
if
(
!
is_page_cache_freeable
(
page
))
{
UnlockPage
(
page
);
if
(
unlikely
(
TryLockPage
(
page
)))
continue
;
}
if
(
PageDirty
(
page
))
{
if
(
PageDirty
(
page
)
&&
is_page_cache_freeable
(
page
)
&&
page
->
mapping
)
{
/*
* It is not critical here to write it only if
* the page is unmapped beause any direct writer
...
...
@@ -461,6 +443,9 @@ static int shrink_cache(int nr_pages, int max_scan, unsigned int gfp_mask)
}
}
if
(
unlikely
(
!
page
->
mapping
))
BUG
();
if
(
unlikely
(
!
spin_trylock
(
&
pagecache_lock
)))
{
/* we hold the page lock so the page cannot go away from under us */
spin_unlock
(
&
pagemap_lru_lock
);
...
...
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