Commit 7176b206 authored by Linus Torvalds's avatar Linus Torvalds

Import 2.3.12pre4

parent 77725b26
......@@ -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/parport/Config.in
endmenu
source drivers/pnp/Config.in
......
......@@ -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;
}
......
......@@ -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;
}
......
......@@ -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) {
......
......@@ -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_tds_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_tds_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() */
......
......@@ -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 */
/*
......
......@@ -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;
......
......@@ -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);
}
......
......@@ -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();
......
......@@ -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);
}
......
......@@ -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)
{
/*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment