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
7176b206
Commit
7176b206
authored
Nov 23, 2007
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Import 2.3.12pre4
parent
77725b26
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
376 additions
and
264 deletions
+376
-264
arch/alpha/config.in
arch/alpha/config.in
+1
-1
arch/i386/kernel/process.c
arch/i386/kernel/process.c
+14
-35
drivers/usb/mouse.c
drivers/usb/mouse.c
+3
-3
drivers/usb/ohci-debug.c
drivers/usb/ohci-debug.c
+11
-0
drivers/usb/ohci.c
drivers/usb/ohci.c
+261
-184
drivers/usb/ohci.h
drivers/usb/ohci.h
+14
-6
drivers/usb/usb_scsi.c
drivers/usb/usb_scsi.c
+55
-20
fs/buffer.c
fs/buffer.c
+1
-1
fs/exec.c
fs/exec.c
+1
-1
include/asm-i386/desc.h
include/asm-i386/desc.h
+15
-4
include/asm-i386/mmu_context.h
include/asm-i386/mmu_context.h
+0
-9
No files found.
arch/alpha/config.in
View file @
7176b206
...
...
@@ -188,7 +188,7 @@ tristate 'Kernel support for a.out (ECOFF) binaries' CONFIG_BINFMT_AOUT
tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
tristate 'Kernel support for Linux/Intel ELF binaries' CONFIG_BINFMT_EM86
source drivers/parpor/Config.in
source drivers/parpor
t
/Config.in
endmenu
source drivers/pnp/Config.in
...
...
arch/i386/kernel/process.c
View file @
7176b206
...
...
@@ -322,14 +322,9 @@ void machine_restart(char * __unused)
pg0
[
0
]
=
_PAGE_RW
|
_PAGE_PRESENT
;
/*
* Use `swapper_pg_dir' as our page directory. We bother with
* `SET_PAGE_DIR' because although might be rebooting, but if we change
* the way we set root page dir in the future, then we wont break a
* seldom used feature ;)
* Use `swapper_pg_dir' as our page directory.
*/
current
->
mm
->
pgd
=
swapper_pg_dir
;
current
->
active_mm
->
pgd
=
swapper_pg_dir
;
activate_context
();
asm
volatile
(
"movl %0,%%cr3"
:
:
"r"
(
__pa
(
swapper_pg_dir
)));
/* Write 0x1234 to absolute memory location 0x472. The BIOS reads
this on booting to tell it to "Bypass memory test (also warm
...
...
@@ -490,16 +485,7 @@ void release_segments(struct mm_struct *mm)
*/
if
(
ldt
)
{
mm
->
segments
=
NULL
;
/*
* special case, when we release the LDT from under
* the running CPU. Other CPUs cannot possibly use
* this LDT as we were getting here through mmput() ...
*/
if
(
mm
==
current
->
mm
)
load_LDT
(
mm
);
/*
* Nobody anymore uses the LDT, we can free it:
*/
clear_LDT
();
vfree
(
ldt
);
}
}
...
...
@@ -581,12 +567,8 @@ void release_thread(struct task_struct *dead_task)
}
/*
* If new_mm is NULL, we're being called to set up the LDT for
* a clone task: this is easy since the clone is not running yet.
* otherwise we copy the old segment into a new segment.
*
* we do not have to muck with descriptors here, that is
* done in
__switch_to() and get_mmu_context()
.
* done in
switch_mm() as needed
.
*/
void
copy_segments
(
struct
task_struct
*
p
,
struct
mm_struct
*
new_mm
)
{
...
...
@@ -597,22 +579,19 @@ void copy_segments(struct task_struct *p, struct mm_struct *new_mm)
/*
* default LDT - use the one from init_task
*/
if
(
new_mm
)
new_mm
->
segments
=
NULL
;
new_mm
->
segments
=
NULL
;
return
;
}
if
(
new_mm
)
{
/*
* Completely new LDT, we initialize it from the parent:
*/
ldt
=
vmalloc
(
LDT_ENTRIES
*
LDT_ENTRY_SIZE
);
if
(
!
ldt
)
printk
(
KERN_WARNING
"ldt allocation failed
\n
"
);
else
memcpy
(
ldt
,
old_ldt
,
LDT_ENTRIES
*
LDT_ENTRY_SIZE
);
new_mm
->
segments
=
ldt
;
}
/*
* Completely new LDT, we initialize it from the parent:
*/
ldt
=
vmalloc
(
LDT_ENTRIES
*
LDT_ENTRY_SIZE
);
if
(
!
ldt
)
printk
(
KERN_WARNING
"ldt allocation failed
\n
"
);
else
memcpy
(
ldt
,
old_ldt
,
LDT_ENTRIES
*
LDT_ENTRY_SIZE
);
new_mm
->
segments
=
ldt
;
return
;
}
...
...
drivers/usb/mouse.c
View file @
7176b206
...
...
@@ -336,15 +336,15 @@ int usb_mouse_init(void)
{
struct
mouse_state
*
mouse
=
&
static_mouse_state
;
misc_register
(
&
usb_mouse
);
mouse
->
present
=
mouse
->
active
=
0
;
mouse
->
irq_handle
=
NULL
;
init_waitqueue_head
(
&
mouse
->
wait
);
mouse
->
fasync
=
NULL
;
misc_register
(
&
usb_mouse
);
usb_register
(
&
mouse_driver
);
printk
(
KERN_INFO
"USB HID boot protocol mouse registered.
\n
"
);
printk
(
KERN_INFO
"USB HID boot protocol mouse
driver
registered.
\n
"
);
return
0
;
}
...
...
drivers/usb/ohci-debug.c
View file @
7176b206
...
...
@@ -131,7 +131,18 @@ void show_ohci_td(struct ohci_td *td)
printk
(
KERN_DEBUG
" next_td = 0x%x
\n
"
,
le32_to_cpup
(
&
td
->
next_td
));
printk
(
KERN_DEBUG
" buf_end = 0x%x
\n
"
,
le32_to_cpup
(
&
td
->
buf_end
));
printk
(
KERN_DEBUG
" ohci TD driver fields:
\n
"
);
printk
(
KERN_DEBUG
" flags = %x {"
,
td
->
hcd_flags
);
if
(
td_allocated
(
*
td
))
printk
(
" alloc"
);
if
(
td_dummy
(
*
td
))
printk
(
" dummy"
);
if
(
td_endofchain
(
*
td
))
printk
(
" endofchain"
);
if
(
!
can_auto_free
(
*
td
))
printk
(
" noautofree"
);
printk
(
"}
\n
"
);
printk
(
KERN_DEBUG
" data = %p
\n
"
,
td
->
data
);
printk
(
KERN_DEBUG
" cmpltd = %p
\n
"
,
td
->
completed
);
printk
(
KERN_DEBUG
" dev_id = %p
\n
"
,
td
->
dev_id
);
printk
(
KERN_DEBUG
" ed = %p
\n
"
,
td
->
ed
);
if
(
td
->
data
!=
NULL
)
{
...
...
drivers/usb/ohci.c
View file @
7176b206
...
...
@@ -111,8 +111,8 @@ static const char *cc_names[16] = {
*
* This function can be called by the interrupt handler.
*/
static
struct
ohci_td
*
ohci_add_td_to_ed
(
struct
ohci_td
*
td
,
struct
ohci_td
*
last_td
,
struct
ohci_ed
*
ed
)
static
struct
ohci_td
*
ohci_add_td
s
_to_ed
(
struct
ohci_td
*
td
,
struct
ohci_ed
*
ed
)
{
struct
ohci_td
*
t
,
*
dummy_td
;
u32
new_dummy
;
...
...
@@ -127,14 +127,14 @@ static struct ohci_td *ohci_add_td_to_ed(struct ohci_td *td,
for
(
t
=
td
;
;
t
=
bus_to_virt
(
le32_to_cpup
(
&
t
->
next_td
)))
{
t
->
ed
=
ed
;
if
(
t
==
last_td
)
if
(
t
->
next_td
==
0
)
break
;
}
/* Make the last TD point back to the first, since it
* will become the new dummy TD. */
new_dummy
=
cpu_to_le32
(
virt_to_bus
(
td
));
last_td
->
next_td
=
new_dummy
;
t
->
next_td
=
new_dummy
;
/* Copy the contents of the first TD into the dummy */
*
dummy_td
=
*
td
;
...
...
@@ -146,34 +146,7 @@ static struct ohci_td *ohci_add_td_to_ed(struct ohci_td *td,
ed
->
tail_td
=
new_dummy
;
return
dummy_td
;
/* replacement head of chain */
}
/* ohci_add_td_to_ed() */
/*
* Add a whole chain of TDs to an ED using the above function.
* The same restrictions apply.
*
* XXX This function is being removed in the future! XXX
*/
static
struct
ohci_td
*
ohci_add_td_chain_to_ed
(
struct
ohci_td
*
td
,
struct
ohci_ed
*
ed
)
{
struct
ohci_td
*
cur_td
;
if
(
!
td
)
return
NULL
;
/* Find the last TD in this chain, storing its pointer in cur_td */
cur_td
=
td
;
for
(;;)
{
__u32
next_td
=
cur_td
->
next_td
;
/* advance to the next td, exit if there isn't one */
if
(
!
next_td
)
break
;
cur_td
=
bus_to_virt
(
le32_to_cpup
(
&
next_td
));
}
return
td
=
ohci_add_td_to_ed
(
td
,
cur_td
,
ed
);
}
/* ohci_add_td_chain_to_ed() */
}
/* ohci_add_tds_to_ed() */
/* .......... */
...
...
@@ -261,6 +234,7 @@ void ohci_add_periodic_ed(struct ohci *ohci, struct ohci_ed *ed, int period)
*/
int_ed
=
&
root_hub
->
ed
[
ms_to_ed_int
(
period
)];
#ifdef OHCI_DEBUG
if
(
MegaDebug
)
printk
(
KERN_DEBUG
"usb-ohci: Using INT ED queue %d for %dms period
\n
"
,
ms_to_ed_int
(
period
),
period
);
#endif
...
...
@@ -277,6 +251,42 @@ void ohci_add_periodic_ed(struct ohci *ohci, struct ohci_ed *ed, int period)
ohci_start_periodic
(
ohci
);
}
/* ohci_add_periodic_ed() */
/*
* Locate the periodic ED for a given interrupt endpoint.
*/
struct
ohci_ed
*
ohci_get_periodic_ed
(
struct
ohci_device
*
dev
,
int
period
,
unsigned
int
pipe
,
int
isoc
)
{
struct
ohci_device
*
root_hub
=
usb_to_ohci
(
dev
->
ohci
->
bus
->
root_hub
);
unsigned
long
flags
;
struct
ohci_ed
*
int_ed
;
unsigned
int
status
,
req_status
;
/* get the dummy ED before the EDs for this period */
int_ed
=
&
root_hub
->
ed
[
ms_to_ed_int
(
period
)];
/* decide on what the status field should look like */
req_status
=
ed_set_maxpacket
(
usb_maxpacket
(
ohci_to_usb
(
dev
),
pipe
))
|
ed_set_speed
(
usb_pipeslow
(
pipe
))
|
(
usb_pipe_endpdev
(
pipe
)
&
0x7ff
)
|
ed_set_type_isoc
(
isoc
);
spin_lock_irqsave
(
&
ohci_edtd_lock
,
flags
);
for
(;;)
{
int_ed
=
bus_to_virt
(
le32_to_cpup
(
&
int_ed
->
next_ed
));
/* stop if we get to the end or to another dummy ED. */
if
(
int_ed
==
0
)
break
;
status
=
le32_to_cpup
(
&
int_ed
->
status
);
if
((
status
&
OHCI_ED_FA
)
==
0
)
break
;
/* check whether all the appropriate fields match */
if
((
status
&
0x7ffa7ff
)
==
req_status
)
return
int_ed
;
}
return
0
;
}
/*
* Put an isochronous ED on the controller's list
*/
...
...
@@ -507,6 +517,7 @@ static int ohci_remove_device_list(__u32 *headp, int devnum)
/* set the controller to skip this one
and remove it from the list */
ed
->
status
|=
cpu_to_le32
(
OHCI_ED_SKIP
);
/* XXX should call td->completed for each td */
*
prevp
=
ed
->
next_ed
;
removed
=
1
;
}
else
{
...
...
@@ -670,6 +681,7 @@ static struct ohci_ed *ohci_get_free_ed(struct ohci_device *dev)
new_ed
->
status
|=
cpu_to_le32
(
OHCI_ED_SKIP
);
/* mark it as allocated */
allocate_ed
(
new_ed
);
new_ed
->
ohci_dev
=
dev
;
return
new_ed
;
}
}
...
...
@@ -722,7 +734,7 @@ struct ohci_td *ohci_fill_new_td(struct ohci_td *td, int dir, int toggle, __u32
flags
);
td
->
cur_buf
=
(
data
==
NULL
)
?
0
:
cpu_to_le32
(
virt_to_bus
(
data
));
td
->
buf_end
=
(
len
==
0
)
?
0
:
cpu_to_le32
(
le32_to_cpup
(
&
td
->
cur_buf
)
+
len
-
1
);
cpu_to_le32
(
virt_to_bus
((
char
*
)
data
+
len
-
1
)
);
/* driver fields */
td
->
data
=
data
;
...
...
@@ -789,31 +801,24 @@ struct ohci_ed *ohci_fill_ed(struct ohci_device *dev, struct ohci_ed *ed,
*
* Returns the head TD in the chain.
*/
struct
ohci_td
*
ohci_build_td_chain
(
struct
ohci_device
*
dev
,
void
*
data
,
unsigned
int
len
,
int
dir
,
__u32
toggle
,
int
round
,
int
auto_free
,
void
*
dev_id
,
usb_device_irq
handler
,
__u32
next_td
)
struct
ohci_td
*
ohci_build_td_chain
(
struct
ohci_device
*
dev
,
void
*
data
,
unsigned
int
len
,
int
dir
,
__u32
toggle
,
int
round
,
int
auto_free
,
void
*
dev_id
,
usb_device_irq
handler
,
__u32
next_td
)
{
struct
ohci_td
*
head
,
*
cur_td
;
__u32
bus_data_start
,
bus_data_end
;
unsigned
short
max_page0_len
;
unsigned
max_len
;
if
(
!
data
||
(
len
==
0
))
return
NULL
;
/*
Setup the first TD, leaving buf_end = 0
*/
/*
Get the first TD
*/
head
=
ohci_get_free_td
(
dev
);
if
(
head
==
NULL
)
{
printk
(
KERN_ERR
"usb-ohci: out of TDs
\n
"
);
return
NULL
;
}
ohci_fill_new_td
(
head
,
td_set_dir_out
(
dir
),
toggle
&
OHCI_TD_DT
,
(
round
?
OHCI_TD_ROUND
:
0
),
data
,
0
,
dev_id
,
handler
);
if
(
!
auto_free
)
noauto_free_td
(
head
);
cur_td
=
head
;
/* AFICT, that the OHCI controller takes care of the innards of
...
...
@@ -821,66 +826,60 @@ struct ohci_td *ohci_build_td_chain(struct ohci_device *dev, void *data, unsigne
* packets as necessary if the transfer falls on an even packet
* size boundary, we don't need a special TD for that. */
while
(
len
>
0
)
{
bus_data_start
=
virt_to_bus
(
data
);
bus_data_end
=
virt_to_bus
(
data
+
(
len
-
1
));
/* check the 4096 byte alignment of the start of the data */
max_page0_len
=
0x1000
-
(
bus_data_start
&
0xfff
);
/* check if the remaining data occupies more than two pages */
if
((
max_page0_len
<
len
)
&&
(
len
-
max_page0_len
>
0x1000
))
{
struct
ohci_td
*
new_td
;
/* Point this TD to data up through the end of
* the second page */
cur_td
->
buf_end
=
bus_data_start
+
(
max_page0_len
+
0xfff
);
/* adjust the data pointer & remaining length */
data
+=
(
max_page0_len
+
0x1000
);
len
-=
(
max_page0_len
+
0x1000
);
/* TODO lookup effect of rounding bit on
* individual TDs vs. whole TD chain transfers;
* disable cur_td's rounding bit here if needed. */
/* check the 4096 byte alignment of the start of the data */
max_len
=
0x2000
-
((
unsigned
long
)
data
&
0xfff
);
/* check if the remaining data occupies more than two pages */
while
(
len
>
max_len
)
{
struct
ohci_td
*
new_td
;
/* TODO lookup effect of rounding bit on
* individual TDs vs. whole TD chain transfers;
* disable cur_td's rounding bit here if needed. */
ohci_fill_new_td
(
cur_td
,
td_set_dir_out
(
dir
),
toggle
&
OHCI_TD_DT
,
(
round
?
OHCI_TD_ROUND
:
0
),
data
,
max_len
-
1
,
dev_id
,
handler
);
if
(
!
auto_free
)
noauto_free_td
(
head
);
/* adjust the data pointer & remaining length */
data
+=
max_len
;
len
-=
max_len
;
/* allocate another td */
new_td
=
ohci_get_free_td
(
dev
);
if
(
new_td
==
NULL
)
{
printk
(
KERN_ERR
"usb-ohci: out of TDs
\n
"
);
/* FIXME: free any allocated TDs */
return
NULL
;
}
/* mark that this is not the last TD... */
clear_td_endofchain
(
cur_td
);
/* Link the new TD to the chain & advance */
cur_td
->
next_td
=
cpu_to_le32
(
virt_to_bus
(
new_td
));
cur_td
=
new_td
;
/* allocate another td */
new_td
=
ohci_get_free_td
(
dev
);
if
(
new_td
==
NULL
)
{
printk
(
KERN_ERR
"usb-ohci: out of TDs
\n
"
);
/* FIXME: free any allocated TDs */
return
NULL
;
}
ohci_fill_new_td
(
new_td
,
td_set_dir_out
(
dir
),
TOGGLE_AUTO
,
/* toggle Data0/1 via the ED */
round
?
OHCI_TD_ROUND
:
0
,
data
,
0
,
dev_id
,
handler
);
if
(
!
auto_free
)
noauto_free_td
(
new_td
);
/* Link the new TD to the chain & advance */
cur_td
->
next_td
=
virt_to_bus
(
new_td
);
cur_td
=
new_td
;
}
else
{
/* Last TD in this chain, normal buf_end is fine */
cur_td
->
buf_end
=
bus_data_end
;
set_td_endofchain
(
cur_td
);
/* address is page-aligned now */
max_len
=
0x2000
;
toggle
=
TOGGLE_AUTO
;
/* toggle Data0/1 via the ED */
}
len
=
0
;
break
;
}
}
/* while */
ohci_fill_new_td
(
cur_td
,
td_set_dir_out
(
dir
),
toggle
&
OHCI_TD_DT
,
(
round
?
OHCI_TD_ROUND
:
0
),
data
,
len
,
dev_id
,
handler
);
if
(
!
auto_free
)
noauto_free_td
(
head
);
/* link the given next_td to the end of this chain */
cur_td
->
next_td
=
next_td
;
cur_td
->
next_td
=
cpu_to_le32
(
next_td
);
if
(
next_td
==
0
)
set_td_endofchain
(
cur_td
);
return
head
;
}
/* ohci_build_td_chain() */
...
...
@@ -902,10 +901,10 @@ static __u16 ohci_td_bytes_done(struct ohci_td *td)
/* if cur_buf is 0, all data has been transferred */
if
(
!
td
->
cur_buf
)
{
return
td
->
buf_end
-
bus_data_start
+
1
;
return
le32_to_cpup
(
&
td
->
buf_end
)
-
bus_data_start
+
1
;
}
bus_data_end
=
td
->
cur_buf
;
bus_data_end
=
le32_to_cpup
(
&
td
->
cur_buf
)
;
/* is it on the same page? */
if
((
bus_data_start
&
~
0xfff
)
==
(
bus_data_end
&
~
0xfff
))
{
...
...
@@ -945,13 +944,36 @@ static void* ohci_request_irq(struct usb_device *usb, unsigned int pipe,
struct
ohci_td
*
td
;
struct
ohci_ed
*
interrupt_ed
;
/* endpoint descriptor for this irq */
int
maxps
=
usb_maxpacket
(
usb
,
pipe
);
unsigned
long
flags
;
/* Get an ED and TD */
interrupt_ed
=
ohci_get_free_ed
(
dev
);
if
(
!
interrupt_ed
)
{
printk
(
KERN_ERR
"Out of EDs on device %p in ohci_request_irq
\n
"
,
dev
);
return
NULL
;
interrupt_ed
=
ohci_get_periodic_ed
(
dev
,
period
,
pipe
,
0
);
if
(
interrupt_ed
==
0
)
{
interrupt_ed
=
ohci_get_free_ed
(
dev
);
if
(
!
interrupt_ed
)
{
printk
(
KERN_ERR
"Out of EDs on device %p in ohci_request_irq
\n
"
,
dev
);
return
NULL
;
}
/*
* Set the max packet size, device speed, endpoint number, usb
* device number (function address), and type of TD.
*/
ohci_fill_ed
(
dev
,
interrupt_ed
,
maxps
,
usb_pipeslow
(
pipe
),
usb_pipe_endpdev
(
pipe
),
0
/* normal TDs */
);
interrupt_ed
->
status
&=
cpu_to_le32
(
~
OHCI_ED_SKIP
);
/* Assimilate the new ED into the collective */
ohci_add_periodic_ed
(
dev
->
ohci
,
interrupt_ed
,
period
);
}
#ifdef OHCI_DEBUG
if
(
MegaDebug
)
{
printk
(
KERN_DEBUG
"ohci_request irq: using ED %p [%x %x %x %x]
\n
"
,
interrupt_ed
,
FIELDS_OF_ED
(
interrupt_ed
));
printk
(
KERN_DEBUG
" for dev %d pipe %x period %d
\n
"
,
usb
->
devnum
,
pipe
,
period
);
}
#endif
td
=
ohci_get_free_td
(
dev
);
if
(
!
td
)
{
...
...
@@ -960,13 +982,6 @@ static void* ohci_request_irq(struct usb_device *usb, unsigned int pipe,
return
NULL
;
}
/*
* Set the max packet size, device speed, endpoint number, usb
* device number (function address), and type of TD.
*/
ohci_fill_ed
(
dev
,
interrupt_ed
,
maxps
,
usb_pipeslow
(
pipe
),
usb_pipe_endpdev
(
pipe
),
0
/* normal TDs */
);
/* Fill in the TD */
if
(
maxps
>
sizeof
(
dev
->
data
))
maxps
=
sizeof
(
dev
->
data
);
...
...
@@ -975,20 +990,15 @@ static void* ohci_request_irq(struct usb_device *usb, unsigned int pipe,
OHCI_TD_ROUND
,
dev
->
data
,
maxps
,
dev_id
,
handler
);
set_td_endofchain
(
td
);
/*
* Put the TD onto our ED and make sure its ready to run
*/
td
=
ohci_add_td_to_ed
(
td
,
td
,
interrupt_ed
);
interrupt_ed
->
status
&=
cpu_to_le32
(
~
OHCI_ED_SKIP
);
ohci_unhalt_ed
(
interrupt_ed
);
/* Make sure all the stores above get done before
* the store which tells the OHCI about the new ed. */
wmb
();
/* Assimilate the new ED into the collective */
ohci_add_periodic_ed
(
dev
->
ohci
,
interrupt_ed
,
period
);
td
->
next_td
=
0
;
spin_lock_irqsave
(
&
ohci_edtd_lock
,
flags
);
td
=
ohci_add_tds_to_ed
(
td
,
interrupt_ed
);
spin_unlock_irqrestore
(
&
ohci_edtd_lock
,
flags
);
return
(
void
*
)
td
;
}
/* ohci_request_irq() */
...
...
@@ -1148,6 +1158,7 @@ static int ohci_control_msg(struct usb_device *usb, unsigned int pipe,
0
/* flags */
,
NULL
/* data */
,
0
/* data len */
,
&
completion_status
,
ohci_control_completed
);
set_td_endofchain
(
status_td
);
status_td
->
next_td
=
0
;
/* end of TDs */
/* If there is data to transfer, create the chain of data TDs
...
...
@@ -1167,18 +1178,18 @@ static int ohci_control_msg(struct usb_device *usb, unsigned int pipe,
}
/* link the to the data & status TDs */
setup_td
->
next_td
=
virt_to_bus
(
data_td
);
setup_td
->
next_td
=
cpu_to_le32
(
virt_to_bus
(
data_td
)
);
}
else
{
/* no data TDs, link to the status TD */
setup_td
->
next_td
=
virt_to_bus
(
status_td
);
setup_td
->
next_td
=
cpu_to_le32
(
virt_to_bus
(
status_td
)
);
}
/*
* Add the control TDs to the control ED (setup_td is the first)
*/
setup_td
=
ohci_add_td
_chain
_to_ed
(
setup_td
,
control_ed
);
control_ed
->
status
&=
~
OHCI_ED_SKIP
;
ohci_unhalt_ed
(
control_ed
);
setup_td
=
ohci_add_td
s
_to_ed
(
setup_td
,
control_ed
);
control_ed
->
status
&=
cpu_to_le32
(
~
OHCI_ED_SKIP
)
;
/* ohci_unhalt_ed(control_ed); */
#ifdef OHCI_DEBUG
if
(
MegaDebug
)
{
...
...
@@ -1201,35 +1212,34 @@ static int ohci_control_msg(struct usb_device *usb, unsigned int pipe,
/* Give the ED to the HC */
ohci_add_control_ed
(
dev
->
ohci
,
control_ed
);
schedule_timeout
(
HZ
/
10
);
schedule_timeout
(
HZ
);
remove_wait_queue
(
&
control_wakeup
,
&
wait
);
#ifdef OHCI_DEBUG
if
(
MegaDebug
)
{
/* complete transaction debugging output (after) */
printk
(
KERN_DEBUG
" *after* Control ED %lx:
\n
"
,
virt_to_bus
(
control_ed
));
show_ohci_ed
(
control_ed
);
printk
(
KERN_DEBUG
" *after* Control TD chain:
\n
"
);
show_ohci_td_chain
(
setup_td
);
printk
(
KERN_DEBUG
" *after* OHCI Controller Status:
\n
"
);
show_ohci_status
(
dev
->
ohci
);
}
#endif
/* no TD cleanup, the TDs were auto-freed as they finished */
/* remove the control ED from the HC */
ohci_remove_control_ed
(
dev
->
ohci
,
control_ed
);
ohci_free_ed
(
control_ed
);
/* return it to the pool */
#ifdef OHCI_DEBUG
if
(
completion_status
!=
0
)
{
const
char
*
what
=
(
completion_status
<
0
)
?
"timed out"
:
cc_names
[
completion_status
&
0xf
];
printk
(
KERN_ERR
"ohci_control_msg: %s on pipe %x cmd %x %x %x %x %x
\n
"
,
printk
(
KERN_ERR
"ohci_control_msg: %s on pipe %x cmd %x %x %x %x %x"
,
what
,
pipe
,
cmd
->
requesttype
,
cmd
->
request
,
cmd
->
value
,
cmd
->
index
,
cmd
->
length
);
if
(
usb_pipeout
(
pipe
)
&&
len
>
0
)
{
int
i
;
printk
(
" data"
);
for
(
i
=
0
;
i
<
16
&&
i
<
len
;
++
i
)
printk
(
" %.2x"
,
((
unsigned
char
*
)
data
)[
i
]);
if
(
i
<
len
)
printk
(
" ..."
);
}
printk
(
"
\n
"
);
if
(
MegaDebug
&&
completion_status
<
0
)
{
printk
(
KERN_DEBUG
"control_ed at %p:
\n
"
,
control_ed
);
show_ohci_ed
(
control_ed
);
if
(
ed_head_td
(
control_ed
)
!=
ed_tail_td
(
control_ed
))
show_ohci_td_chain
(
bus_to_virt
(
ed_head_td
(
control_ed
)));
printk
(
KERN_DEBUG
"setup TD at %p:
\n
"
,
setup_td
);
show_ohci_td
(
setup_td
);
}
}
else
if
(
!
usb_pipeout
(
pipe
))
{
unsigned
char
*
q
=
data
;
int
i
;
...
...
@@ -1243,7 +1253,26 @@ static int ohci_control_msg(struct usb_device *usb, unsigned int pipe,
}
printk
(
"
\n
"
);
}
if
(
MegaDebug
)
{
/* complete transaction debugging output (after) */
printk
(
KERN_DEBUG
" *after* Control ED %lx:
\n
"
,
virt_to_bus
(
control_ed
));
show_ohci_ed
(
control_ed
);
printk
(
KERN_DEBUG
" *after* Control TD chain:
\n
"
);
show_ohci_td_chain
(
setup_td
);
printk
(
KERN_DEBUG
" *after* OHCI Controller Status:
\n
"
);
show_ohci_status
(
dev
->
ohci
);
}
#endif
/* no TD cleanup, the TDs were auto-freed as they finished */
/* remove the control ED from the HC */
ohci_remove_control_ed
(
dev
->
ohci
,
control_ed
);
ohci_free_ed
(
control_ed
);
/* return it to the pool */
if
(
completion_status
<
0
)
completion_status
=
USB_ST_TIMEOUT
;
return
completion_status
;
}
/* ohci_control_msg() */
...
...
@@ -1278,6 +1307,7 @@ static int ohci_bulk_td_handler(int stats, void *buffer, int len, void *dev_id)
req
=
(
struct
ohci_bulk_request_state
*
)
dev_id
;
#ifdef OHCI_DEBUG
if
(
MegaDebug
)
printk
(
KERN_DEBUG
"ohci_bulk_td_handler stats %x, buffer %p, len %d, req %p
\n
"
,
stats
,
buffer
,
len
,
req
);
#endif
...
...
@@ -1285,11 +1315,24 @@ static int ohci_bulk_td_handler(int stats, void *buffer, int len, void *dev_id)
if
(
stats
==
USB_ST_NOERROR
)
req
->
_bytes_done
+=
len
;
#ifdef OHCI_DEBUG
if
(
MegaDebug
&&
req
->
_bytes_done
)
{
int
i
;
printk
(
KERN_DEBUG
" %d bytes, bulk data:"
,
req
->
_bytes_done
);
for
(
i
=
0
;
i
<
16
&&
i
<
req
->
_bytes_done
;
++
i
)
printk
(
" %.2x"
,
((
unsigned
char
*
)
buffer
)[
i
]);
if
(
i
<
req
->
_bytes_done
)
printk
(
" ..."
);
printk
(
"
\n
"
);
}
#endif
/* call the real completion handler when done or on an error */
if
((
stats
!=
USB_ST_NOERROR
)
||
(
req
->
_bytes_done
>=
req
->
length
&&
req
->
completion
!=
NULL
))
{
*
req
->
bytes_transferred_p
+=
req
->
_bytes_done
;
#ifdef OHCI_DEBUG
if
(
MegaDebug
)
printk
(
KERN_DEBUG
"usb-ohci: bulk request %p ending
\n
"
,
req
);
#endif
req
->
completion
(
stats
,
buffer
,
req
->
_bytes_done
,
req
->
dev_id
);
...
...
@@ -1305,7 +1348,7 @@ static int ohci_bulk_td_handler(int stats, void *buffer, int len, void *dev_id)
* to an error.
*
* bytes_transferred_p is a pointer to an integer that will be
*
-incremented- by
the number of bytes that have been successfully
*
set to
the number of bytes that have been successfully
* transferred. The interrupt handler will update it after each
* internal TD completes successfully.
*
...
...
@@ -1329,6 +1372,7 @@ static struct ohci_ed* ohci_request_bulk(struct ohci_bulk_request_state *bulk_re
unsigned
long
flags
;
#ifdef OHCI_DEBUG
if
(
MegaDebug
)
printk
(
KERN_DEBUG
"ohci_request_bulk(%p) ohci_dev %p, completion %p, pipe %x, data %p, len %d
\n
"
,
bulk_request
,
dev
,
bulk_request
->
completion
,
pipe
,
data
,
len
);
#endif
...
...
@@ -1358,6 +1402,10 @@ static struct ohci_ed* ohci_request_bulk(struct ohci_bulk_request_state *bulk_re
usb_pipeslow
(
pipe
),
usb_pipe_endpdev
(
pipe
),
0
/* bulk uses normal TDs */
);
/* initialize the toggle carry */
if
(
usb_gettoggle
(
usb_dev
,
usb_pipeendpoint
(
pipe
),
usb_pipeout
(
pipe
)))
ohci_ed_set_carry
(
bulk_ed
);
/* initialize the internal counter */
bulk_request
->
_bytes_done
=
0
;
...
...
@@ -1365,13 +1413,11 @@ static struct ohci_ed* ohci_request_bulk(struct ohci_bulk_request_state *bulk_re
* Add the TDs to the ED
*/
spin_lock_irqsave
(
&
ohci_edtd_lock
,
flags
);
bulk_ed
->
status
|=
OHCI_ED_SKIP
;
head_td
=
ohci_add_td_chain_to_ed
(
head_td
,
bulk_ed
);
bulk_ed
->
status
&=
~
OHCI_ED_SKIP
;
ohci_unhalt_ed
(
bulk_ed
);
head_td
=
ohci_add_tds_to_ed
(
head_td
,
bulk_ed
);
bulk_ed
->
status
&=
cpu_to_le32
(
~
OHCI_ED_SKIP
);
/* ohci_unhalt_ed(bulk_ed); */
spin_unlock_irqrestore
(
&
ohci_edtd_lock
,
flags
);
#ifdef OHCI_DEBUG
if
(
MegaDebug
)
{
/* complete request debugging output (before) */
...
...
@@ -1414,7 +1460,8 @@ static int ohci_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, void *da
struct
ohci_bulk_request_state
req
;
struct
ohci_ed
*
req_ed
;
#ifdef OHCI_DEBUG
#ifdef OHCI_DEBUG
if
(
MegaDebug
)
printk
(
KERN_DEBUG
"ohci_bulk_msg %p pipe %x, data %p, len %d, bytes_transferred %p
\n
"
,
usb_dev
,
pipe
,
data
,
len
,
bytes_transferred_p
);
#endif
...
...
@@ -1430,6 +1477,12 @@ static int ohci_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, void *da
req
.
bytes_transferred_p
=
bytes_transferred_p
;
req
.
dev_id
=
&
completion_status
;
req
.
completion
=
ohci_bulk_msg_completed
;
if
(
bytes_transferred_p
)
*
bytes_transferred_p
=
0
;
if
(
usb_endpoint_halted
(
usb_dev
,
usb_pipeendpoint
(
pipe
))
&&
usb_clear_halt
(
usb_dev
,
usb_pipeendpoint
(
pipe
)
|
(
pipe
&
0x80
)))
return
USB_ST_STALL
;
/*
* Start the transaction..
...
...
@@ -1442,7 +1495,8 @@ static int ohci_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, void *da
/* FIXME this should to wait for a caller specified time... */
schedule_timeout
(
HZ
*
5
);
/* it'll only stay in this state of the request never finished */
/* completion_status will only stay in this state of the
* request never finished */
if
(
completion_status
==
USB_ST_INTERNALERROR
)
{
struct
ohci_device
*
dev
=
usb_to_ohci
(
usb_dev
);
struct
ohci_regs
*
regs
=
dev
->
ohci
->
regs
;
...
...
@@ -1485,9 +1539,15 @@ static int ohci_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, void *da
/* remove the ED from the HC */
ohci_remove_bulk_ed
(
usb_to_ohci
(
usb_dev
)
->
ohci
,
req_ed
);
/* save the toggle value back into the usb_dev */
usb_settoggle
(
usb_dev
,
usb_pipeendpoint
(
pipe
),
usb_pipeout
(
pipe
),
ohci_ed_carry
(
req_ed
));
ohci_free_ed
(
req_ed
);
/* return it to the pool */
#ifdef OHCI_DEBUG
if
(
completion_status
!=
0
||
MegaDebug
)
printk
(
KERN_DEBUG
"ohci_bulk_msg done, status %x (bytes_transferred = %ld).
\n
"
,
completion_status
,
*
bytes_transferred_p
);
#endif
...
...
@@ -1659,7 +1719,6 @@ static int start_hc(struct ohci *ohci)
struct
ohci_device
*
root_hub
=
usb_to_ohci
(
ohci
->
bus
->
root_hub
);
fminterval
=
readl
(
&
ohci
->
regs
->
fminterval
)
&
0x3fff
;
#if 0
printk(KERN_DEBUG "entering start_hc %p\n", ohci);
#endif
...
...
@@ -1671,16 +1730,22 @@ static int start_hc(struct ohci *ohci)
writel
(
virt_to_bus
(
root_hub
->
hcca
),
&
ohci
->
regs
->
hcca
);
/*
*
XXX Should fminterval also be set here?
*
The spec suggests 0x2edf [11,999]. (FIXME: make this a constant)
*
fminterval has to be 11999 (it can be adjusted +/- 1
*
to sync with other things if necessary).
*/
/* fminterval |= (0x2edf << 16); */
fminterval
=
(
10240
<<
16
)
|
11999
;
writel
(
fminterval
,
&
ohci
->
regs
->
fminterval
);
fminterval
=
11999
;
/* Start periodic transfers at 90% of fminterval (fmremaining
* counts down; this will put them in the first 10% of the
* frame). */
writel
((
0x2edf
*
9
)
/
10
,
&
ohci
->
regs
->
periodicstart
);
writel
((
fminterval
*
9
)
/
10
,
&
ohci
->
regs
->
periodicstart
);
/* Set largest data packet counter and frame interval. */
fminterval
|=
((
fminterval
-
210
)
*
6
/
7
)
<<
16
;
writel
(
fminterval
,
&
ohci
->
regs
->
fminterval
);
/* Set low-speed threshold (value from MacOS) */
writel
(
1576
,
&
ohci
->
regs
->
lsthresh
);
/*
* FNO (frame number overflow) could be enabled... they
...
...
@@ -1926,7 +1991,8 @@ static void ohci_reap_donelist(struct ohci *ohci)
struct
ohci_td
*
td
;
/* used for walking the list */
/* um... isn't this dangerous to do in an interrupt handler? -greg */
// spin_lock(&ohci_edtd_lock);
/* nope. -paulus */
spin_lock
(
&
ohci_edtd_lock
);
/* create the FIFO ordered donelist */
td
=
ohci_reverse_donelist
(
ohci
);
...
...
@@ -1934,18 +2000,33 @@ static void ohci_reap_donelist(struct ohci *ohci)
while
(
td
!=
NULL
)
{
struct
ohci_td
*
next_td
=
td
->
next_dl_td
;
int
cc
=
OHCI_TD_CC_GET
(
le32_to_cpup
(
&
td
->
info
));
struct
ohci_ed
*
ed
=
td
->
ed
;
if
(
td_dummy
(
*
td
))
printk
(
KERN_ERR
"yikes! reaping a dummy TD
\n
"
);
if
(
cc
!=
0
&&
ohci_ed_halted
(
td
->
ed
)
&&
!
td_endofchain
(
*
td
))
{
#ifdef OHCI_DEBUG
if
(
cc
!=
0
&&
MegaDebug
)
{
printk
(
"cc=%s on td %p (ed %p)
\n
"
,
cc_names
[
cc
],
td
,
ed
);
show_ohci_td
(
td
);
show_ohci_ed
(
ed
);
if
(
ed_head_td
(
ed
)
!=
ed_tail_td
(
ed
))
show_ohci_td_chain
(
bus_to_virt
(
ed_head_td
(
ed
)));
}
#endif
if
(
cc
==
USB_ST_STALL
)
{
/* mark endpoint as halted */
usb_endpoint_halt
(
ed
->
ohci_dev
->
usb
,
ed_get_en
(
ed
));
}
if
(
cc
!=
0
&&
ohci_ed_halted
(
ed
)
&&
!
td_endofchain
(
*
td
))
{
/*
* There was an error on this TD and the ED
* is halted, and this was not the last TD
* of the transaction, so there will be TDs
* to clean off the ED.
*/
struct
ohci_ed
*
ed
=
td
->
ed
;
struct
ohci_td
*
tail_td
=
bus_to_virt
(
ed_tail_td
(
ed
));
struct
ohci_td
*
ntd
;
...
...
@@ -1953,24 +2034,17 @@ static void ohci_reap_donelist(struct ohci *ohci)
td
=
ntd
=
bus_to_virt
(
ed_head_td
(
ed
));
while
(
td
!=
tail_td
)
{
ntd
=
bus_to_virt
(
le32_to_cpup
(
&
td
->
next_td
));
if
(
td_endofchain
(
*
td
))
break
;
/* only deal with TDs from this ED,
* the host controller could have
* processed other endpoints at the
* same time as this one.. */
if
(
td
->
ed
==
ed
)
{
if
(
td_endofchain
(
*
td
))
break
;
/* FIXME: unlink this TD from the
* reverse donelist! */
ohci_free_td
(
td
);
}
printk
(
KERN_DEBUG
"skipping TD %p
\n
"
,
td
);
ohci_free_td
(
td
);
td
=
ntd
;
}
/* Set the ED head past the ones we cleaned
off, and clear the halted flag */
printk
(
KERN_DEBUG
"restarting ED %p at TD %p
\n
"
,
ed
,
ntd
);
set_ed_head_td
(
ed
,
virt_to_bus
(
ntd
));
ohci_unhalt_ed
(
ed
);
/* If we didn't find an endofchain TD, give up */
...
...
@@ -1996,8 +2070,9 @@ static void ohci_reap_donelist(struct ohci *ohci)
td
->
cur_buf
=
cpu_to_le32
(
virt_to_bus
(
td
->
data
));
/* insert it back on its ED */
ohci_add_td_to_ed
(
td
,
td
,
td
->
ed
);
ohci_unhalt_ed
(
td
->
ed
);
td
->
next_td
=
0
;
ohci_add_tds_to_ed
(
td
,
ed
);
/* ohci_unhalt_ed(td->ed); */
}
else
{
/* return it to the pool of free TDs */
if
(
can_auto_free
(
*
td
))
...
...
@@ -2007,7 +2082,7 @@ static void ohci_reap_donelist(struct ohci *ohci)
td
=
next_td
;
}
//
spin_unlock(&ohci_edtd_lock);
spin_unlock
(
&
ohci_edtd_lock
);
}
/* ohci_reap_donelist() */
...
...
@@ -2259,8 +2334,10 @@ static struct ohci *alloc_ohci(void* mem_base)
writel
(
0
,
&
ohci
->
regs
->
ed_bulkhead
);
#ifdef OHCI_DEBUG
if
(
MegaDebug
)
{
printk
(
KERN_DEBUG
"alloc_ohci(): controller
\n
"
);
show_ohci_status
(
ohci
);
}
#endif
#if 0
...
...
@@ -2333,7 +2410,7 @@ static int ohci_control_thread(void * __ohci)
printk
(
KERN_DEBUG
"ohci-control thread code for 0x%p code at 0x%p
\n
"
,
__ohci
,
&
ohci_control_thread
);
exit_mm
(
current
);
exit_files
(
current
);
exit_fs
(
current
);
/*exit_fs(current);*/
/* can't do kernel_thread if we do this */
strcpy
(
current
->
comm
,
"ohci-control"
);
...
...
@@ -2398,6 +2475,7 @@ static int ohci_control_thread(void * __ohci)
#endif
}
else
{
/* unknown signal, exit the thread */
printk
(
KERN_DEBUG
"usb-ohci: control thread for %p exiting on signal %ld
\n
"
,
__ohci
,
signr
);
break
;
}
}
...
...
@@ -2406,7 +2484,6 @@ static int ohci_control_thread(void * __ohci)
reset_hc
(
ohci
);
release_ohci
(
ohci
);
usb_deregister_bus
(
ohci
->
bus
);
printk
(
KERN_DEBUG
"ohci-control thread for 0x%p exiting
\n
"
,
__ohci
);
return
0
;
}
/* ohci_control_thread() */
...
...
drivers/usb/ohci.h
View file @
7176b206
...
...
@@ -41,8 +41,7 @@ struct ohci_td {
/* bit0: Is this TD allocated? */
/* bit1: Is this a dummy (end of list) TD? */
/* bit2: do NOT automatically free this TD on completion */
/* bit3: this is NOT the last TD in a contiguious TD chain
* on the indicated ED. (0 means it is the last) */
/* bit3: this is the last TD in a contiguious TD chain */
struct
usb_device
*
usb_dev
;
/* the owning device */
...
...
@@ -86,9 +85,9 @@ struct ohci_td {
#define make_dumb_td(td) ((td)->hcd_flags |= 2)
#define clear_dumb_td(td) ((td)->hcd_flags &= ~(__u32)2)
#define td_endofchain(td) (
!((td).hcd_flags & (1 << 3)
))
#define
set
_td_endofchain(td) ((td)->hcd_flags &= ~(1 << 3))
#define
clear
_td_endofchain(td) ((td)->hcd_flags |= (1 << 3))
#define td_endofchain(td) (
(td).hcd_flags & (1 << 3
))
#define
clear
_td_endofchain(td) ((td)->hcd_flags &= ~(1 << 3))
#define
set
_td_endofchain(td) ((td)->hcd_flags |= (1 << 3))
/*
* These control if the IRQ will call ohci_free_td after taking the TDs
...
...
@@ -109,6 +108,10 @@ struct ohci_ed {
__u32
tail_td
;
/* TD Queue tail pointer */
__u32
_head_td
;
/* TD Queue head pointer, toggle carry & halted bits */
__u32
next_ed
;
/* Next ED */
/* driver fields */
struct
ohci_device
*
ohci_dev
;
struct
ohci_ed
*
ed_chain
;
}
__attribute
((
aligned
(
16
)));
/* get the head_td */
...
...
@@ -119,10 +122,13 @@ struct ohci_ed {
#define set_ed_head_td(ed, td) ((ed)->_head_td = cpu_to_le32((td)) \
| ((ed)->_head_td & cpu_to_le32(3)))
/* Control the ED's halted
flag
*/
/* Control the ED's halted
and carry flags
*/
#define ohci_halt_ed(ed) ((ed)->_head_td |= cpu_to_le32(1))
#define ohci_unhalt_ed(ed) ((ed)->_head_td &= cpu_to_le32(~(__u32)1))
#define ohci_ed_halted(ed) ((ed)->_head_td & cpu_to_le32(1))
#define ohci_ed_set_carry(ed) ((ed)->_head_td |= cpu_to_le32(2))
#define ohci_ed_clr_carry(ed) ((ed)->_head_td &= ~cpu_to_le32(2))
#define ohci_ed_carry(ed) ((le32_to_cpup(&(ed)->_head_td) >> 1) & 1)
#define OHCI_ED_SKIP (1 << 14)
#define OHCI_ED_MPS (0x7ff << 16)
...
...
@@ -142,6 +148,8 @@ struct ohci_ed {
#define OHCI_ED_EN (0xf << 7)
#define OHCI_ED_FA (0x7f)
#define ed_get_en(ed) ((le32_to_cpup(&(ed)->status) & OHCI_ED_EN) >> 7)
#define ed_get_fa(ed) (le32_to_cpup(&(ed)->status) & OHCI_ED_FA)
/* NOTE: bits 27-31 of the status dword are reserved for the HCD */
/*
...
...
drivers/usb/usb_scsi.c
View file @
7176b206
...
...
@@ -139,10 +139,20 @@ static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)
this_xfer
=
length
>
max_size
?
max_size
:
length
;
length
-=
this_xfer
;
do
{
US_DEBUGP
(
"Bulk xfer %x(%d)
\n
"
,
(
unsigned
int
)
buf
,
this_xfer
);
/*US_DEBUGP("Bulk xfer %x(%d)\n", (unsigned int)buf, this_xfer);*/
result
=
us
->
pusb_dev
->
bus
->
op
->
bulk_msg
(
us
->
pusb_dev
,
pipe
,
buf
,
this_xfer
,
&
partial
);
if
(
result
!=
0
||
partial
!=
this_xfer
)
US_DEBUGP
(
"bulk_msg returned %d xferred %lu/%d
\n
"
,
result
,
partial
,
this_xfer
);
if
(
result
==
USB_ST_STALL
)
{
US_DEBUGP
(
"clearing endpoing halt for pipe %x
\n
"
,
pipe
);
usb_clear_halt
(
us
->
pusb_dev
,
usb_pipeendpoint
(
pipe
)
|
(
pipe
&
0x80
));
}
/* we want to retry if the device reported NAK */
if
(
result
==
USB_ST_TIMEOUT
)
{
if
(
partial
!=
this_xfer
)
{
...
...
@@ -171,28 +181,31 @@ static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)
return
0
;
}
static
int
us_transfer
(
Scsi_Cmnd
*
srb
,
int
dir_in
)
{
struct
us_data
*
us
=
(
struct
us_data
*
)
srb
->
host_scribble
;
int
i
;
int
result
=
-
1
;
unsigned
int
pipe
=
dir_in
?
usb_rcvbulkpipe
(
us
->
pusb_dev
,
us
->
ep_in
)
:
usb_sndbulkpipe
(
us
->
pusb_dev
,
us
->
ep_out
);
if
(
srb
->
use_sg
)
{
struct
scatterlist
*
sg
=
(
struct
scatterlist
*
)
srb
->
request_buffer
;
for
(
i
=
0
;
i
<
srb
->
use_sg
;
i
++
)
{
result
=
us_one_transfer
(
us
,
dir_in
?
usb_rcvbulkpipe
(
us
->
pusb_dev
,
us
->
ep_in
)
:
usb_sndbulkpipe
(
us
->
pusb_dev
,
us
->
ep_out
),
sg
[
i
].
address
,
sg
[
i
].
length
);
result
=
us_one_transfer
(
us
,
pipe
,
sg
[
i
].
address
,
sg
[
i
].
length
);
if
(
result
)
break
;
}
return
result
;
}
else
return
us_one_transfer
(
us
,
dir_in
?
usb_rcvbulkpipe
(
us
->
pusb_dev
,
us
->
ep_in
)
:
usb_sndbulkpipe
(
us
->
pusb_dev
,
us
->
ep_out
),
srb
->
request_buffer
,
srb
->
request_bufflen
);
result
=
us_one_transfer
(
us
,
pipe
,
srb
->
request_buffer
,
srb
->
request_bufflen
);
if
(
result
)
US_DEBUGP
(
"us_transfer returning error %d
\n
"
,
result
);
return
result
;
}
static
unsigned
int
us_transfer_length
(
Scsi_Cmnd
*
srb
)
...
...
@@ -232,12 +245,13 @@ static int pop_CBI_irq(int state, void *buffer, int len, void *dev_id)
struct
us_data
*
us
=
(
struct
us_data
*
)
dev_id
;
if
(
state
!=
USB_ST_REMOVED
)
{
us
->
ip_data
=
*
(
__u16
*
)
buffer
;
US_DEBUGP
(
"Interrupt Status %x
\n
"
,
us
->
ip_data
);
us
->
ip_data
=
le16_to_cpup
((
__u16
*
)
buffer
)
;
/* US_DEBUGP("Interrupt Status %x\n", us->ip_data); */
}
if
(
us
->
ip_wanted
)
if
(
us
->
ip_wanted
)
{
us
->
ip_wanted
=
0
;
wake_up
(
&
us
->
ip_waitq
);
us
->
ip_wanted
=
0
;
}
/* we dont want another interrupt */
...
...
@@ -250,6 +264,7 @@ static int pop_CB_reset(struct us_data *us)
devrequest
dr
;
int
result
;
US_DEBUGP
(
"pop_CB_reset
\n
"
);
dr
.
requesttype
=
USB_TYPE_CLASS
|
USB_RT_INTERFACE
;
dr
.
request
=
US_CBI_ADSC
;
dr
.
value
=
0
;
...
...
@@ -262,12 +277,15 @@ static int pop_CB_reset(struct us_data *us)
usb_sndctrlpipe
(
us
->
pusb_dev
,
0
),
&
dr
,
cmd
,
12
);
usb_clear_halt
(
us
->
pusb_dev
,
us
->
ep_in
|
0x80
);
usb_clear_halt
(
us
->
pusb_dev
,
us
->
ep_out
);
/* long wait for reset */
schedule_timeout
(
HZ
*
5
);
US_DEBUGP
(
"pop_CB_reset: clearing endpoint halt
\n
"
);
usb_clear_halt
(
us
->
pusb_dev
,
us
->
ep_in
|
0x80
);
usb_clear_halt
(
us
->
pusb_dev
,
us
->
ep_out
);
US_DEBUGP
(
"pop_CB_reset done
\n
"
);
return
0
;
}
...
...
@@ -325,6 +343,7 @@ static int pop_CB_command(Scsi_Cmnd *srb)
/* as per spec try a start command, wait and retry */
done_start
++
;
memset
(
cmd
,
0
,
sizeof
(
cmd
));
cmd
[
0
]
=
START_STOP
;
cmd
[
4
]
=
1
;
/* start */
result
=
us
->
pusb_dev
->
bus
->
op
->
control_msg
(
us
->
pusb_dev
,
...
...
@@ -338,7 +357,7 @@ static int pop_CB_command(Scsi_Cmnd *srb)
result
=
us
->
pusb_dev
->
bus
->
op
->
control_msg
(
us
->
pusb_dev
,
usb_sndctrlpipe
(
us
->
pusb_dev
,
0
),
&
dr
,
srb
->
cmnd
,
srb
->
cmd_len
);
if
(
result
!=
USB_ST_STALL
&&
result
!=
USB_ST_TIMEOUT
)
if
(
/*result != USB_ST_STALL &&*/
result
!=
USB_ST_TIMEOUT
)
return
result
;
}
return
result
;
...
...
@@ -356,6 +375,7 @@ static int pop_CB_status(Scsi_Cmnd *srb)
devrequest
dr
;
int
retry
=
5
;
US_DEBUGP
(
"pop_CB_status, proto=%x
\n
"
,
us
->
protocol
);
switch
(
us
->
protocol
)
{
case
US_PR_CB
:
/* get from control */
...
...
@@ -439,23 +459,26 @@ static int pop_CBI(Scsi_Cmnd *srb)
if
(
result
==
USB_ST_STALL
||
result
==
USB_ST_TIMEOUT
)
{
return
(
DID_OK
<<
16
)
|
2
;
}
return
DID_
ABORT
<<
16
;
return
DID_
ERROR
<<
16
;
}
/* transfer the data */
if
(
us_transfer_length
(
srb
))
{
result
=
us_transfer
(
srb
,
US_DIRECTION
(
srb
->
cmnd
[
0
]));
if
(
result
&&
result
!=
USB_ST_DATAUNDERRUN
)
{
if
(
result
&&
result
!=
USB_ST_DATAUNDERRUN
&&
result
!=
USB_ST_STALL
)
{
US_DEBUGP
(
"CBI transfer %x
\n
"
,
result
);
return
DID_ABORT
<<
16
;
}
else
if
(
result
==
USB_ST_DATAUNDERRUN
)
{
return
DID_ERROR
<<
16
;
}
#if 0
else if (result == USB_ST_DATAUNDERRUN) {
return DID_OK << 16;
}
} else {
if (!result) {
return DID_OK << 16;
}
#endif
}
/* get status */
...
...
@@ -947,6 +970,7 @@ static int usbscsi_control_thread(void * __us)
US_DEBUGP
(
"Old/New length = %d/%d
\n
"
,
savelen
,
length
);
if
(
us
->
srb
->
request_bufflen
!=
length
)
{
US_DEBUGP
(
"redoing cmd with len=%d
\n
"
,
length
);
us
->
srb
->
request_bufflen
=
length
;
us
->
srb
->
result
=
us
->
pop
(
us
->
srb
);
}
...
...
@@ -957,6 +981,15 @@ static int usbscsi_control_thread(void * __us)
case
REQUEST_SENSE
:
case
INQUIRY
:
case
MODE_SENSE
:
if
(
us
->
srb
->
use_sg
==
0
&&
length
>
0
)
{
int
i
;
printk
(
KERN_DEBUG
"Data is"
);
for
(
i
=
0
;
i
<
32
&&
i
<
length
;
++
i
)
printk
(
" %.2x"
,
((
unsigned
char
*
)
us
->
srb
->
request_buffer
)[
i
]);
if
(
i
<
length
)
printk
(
" ..."
);
printk
(
"
\n
"
);
}
us
->
srb
->
cmnd
[
4
]
=
saveallocation
;
break
;
...
...
@@ -969,6 +1002,7 @@ static int usbscsi_control_thread(void * __us)
}
/* force attention on first command */
if
(
!
us
->
attention_done
)
{
US_DEBUGP
(
"forcing unit attention
\n
"
);
if
(
us
->
srb
->
cmnd
[
0
]
==
REQUEST_SENSE
)
{
if
(
us
->
srb
->
result
==
(
DID_OK
<<
16
))
{
unsigned
char
*
p
=
(
unsigned
char
*
)
us
->
srb
->
request_buffer
;
...
...
@@ -987,6 +1021,7 @@ static int usbscsi_control_thread(void * __us)
}
}
}
US_DEBUGP
(
"scsi cmd done, result=%x
\n
"
,
us
->
srb
->
result
);
us
->
srb
->
scsi_done
(
us
->
srb
);
us
->
srb
=
NULL
;
break
;
...
...
fs/buffer.c
View file @
7176b206
...
...
@@ -1972,7 +1972,7 @@ void end_lazy_tlb(struct mm_struct *mm)
current
->
mm
=
mm
;
if
(
mm
!=
active_mm
)
{
current
->
active_mm
=
mm
;
activate_context
(
);
switch_mm
(
active_mm
,
mm
);
}
mmdrop
(
active_mm
);
}
...
...
fs/exec.c
View file @
7176b206
...
...
@@ -384,7 +384,7 @@ static int exec_mmap(void)
mm
->
cpu_vm_mask
=
(
1UL
<<
smp_processor_id
());
current
->
mm
=
mm
;
current
->
active_mm
=
mm
;
activate_context
(
);
switch_mm
(
active_mm
,
mm
);
mm_release
();
if
(
old_mm
)
{
if
(
active_mm
!=
old_mm
)
BUG
();
...
...
include/asm-i386/desc.h
View file @
7176b206
...
...
@@ -69,17 +69,28 @@ extern void set_intr_gate(unsigned int irq, void * addr);
extern
void
set_ldt_desc
(
unsigned
int
n
,
void
*
addr
,
unsigned
int
size
);
extern
void
set_tss_desc
(
unsigned
int
n
,
void
*
addr
);
extern
inline
void
clear_LDT
(
void
)
{
int
cpu
=
smp_processor_id
();
set_ldt_desc
(
cpu
,
&
default_ldt
,
1
);
__load_LDT
(
cpu
);
}
/*
* load one particular LDT into the current CPU
*/
extern
inline
void
load_LDT
(
struct
mm_struct
*
mm
)
{
int
cpu
=
smp_processor_id
();
void
*
segments
=
mm
->
segments
;
int
count
=
LDT_ENTRIES
;
if
(
mm
->
segments
)
set_ldt_desc
(
cpu
,
mm
->
segments
,
LDT_ENTRIES
);
else
set_ldt_desc
(
cpu
,
&
default_ldt
,
1
);
if
(
!
segments
)
{
segments
=
&
default_ldt
;
count
=
1
;
}
set_ldt_desc
(
cpu
,
segments
,
count
);
__load_LDT
(
cpu
);
}
...
...
include/asm-i386/mmu_context.h
View file @
7176b206
...
...
@@ -9,15 +9,6 @@
#define destroy_context(mm) do { } while(0)
#define init_new_context(tsk,mm) do { } while (0)
static
inline
void
activate_context
(
void
)
{
struct
task_struct
*
tsk
=
current
;
struct
mm_struct
*
mm
=
tsk
->
mm
;
load_LDT
(
mm
);
__asm__
__volatile__
(
"movl %0,%%cr3"
:
:
"r"
(
__pa
(
mm
->
pgd
)));
}
static
inline
void
switch_mm
(
struct
mm_struct
*
prev
,
struct
mm_struct
*
next
)
{
/*
...
...
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