From 7176b206acad22d4276ded88442b5ac16f0812f0 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:26:25 -0500 Subject: [PATCH] Import 2.3.12pre4 --- arch/alpha/config.in | 2 +- arch/i386/kernel/process.c | 49 ++-- drivers/usb/mouse.c | 6 +- drivers/usb/ohci-debug.c | 11 + drivers/usb/ohci.c | 445 +++++++++++++++++++-------------- drivers/usb/ohci.h | 20 +- drivers/usb/usb_scsi.c | 75 ++++-- fs/buffer.c | 2 +- fs/exec.c | 2 +- include/asm-i386/desc.h | 19 +- include/asm-i386/mmu_context.h | 9 - 11 files changed, 376 insertions(+), 264 deletions(-) diff --git a/arch/alpha/config.in b/arch/alpha/config.in index 0c00ff22f106..46c4a470bf46 100644 --- a/arch/alpha/config.in +++ b/arch/alpha/config.in @@ -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 diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index d98600fddfb6..b506facc1c1b 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c @@ -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; } diff --git a/drivers/usb/mouse.c b/drivers/usb/mouse.c index 4b4be164d617..44ab90986265 100644 --- a/drivers/usb/mouse.c +++ b/drivers/usb/mouse.c @@ -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; } diff --git a/drivers/usb/ohci-debug.c b/drivers/usb/ohci-debug.c index 8bf2736921bb..339652d210e5 100644 --- a/drivers/usb/ohci-debug.c +++ b/drivers/usb/ohci-debug.c @@ -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) { diff --git a/drivers/usb/ohci.c b/drivers/usb/ohci.c index dd54f77e37f5..65798e6d21de 100644 --- a/drivers/usb/ohci.c +++ b/drivers/usb/ohci.c @@ -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() */ diff --git a/drivers/usb/ohci.h b/drivers/usb/ohci.h index 804a7297610c..4bb71c55ce2e 100644 --- a/drivers/usb/ohci.h +++ b/drivers/usb/ohci.h @@ -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 */ /* diff --git a/drivers/usb/usb_scsi.c b/drivers/usb/usb_scsi.c index 5701d26710f2..3099c9826e43 100644 --- a/drivers/usb/usb_scsi.c +++ b/drivers/usb/usb_scsi.c @@ -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; diff --git a/fs/buffer.c b/fs/buffer.c index f578992b3b2f..11cfc4145dc8 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -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); } diff --git a/fs/exec.c b/fs/exec.c index 5e614d8cdef7..e3d6fa4b7e28 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -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(); diff --git a/include/asm-i386/desc.h b/include/asm-i386/desc.h index 31e267386415..3b29aac27207 100644 --- a/include/asm-i386/desc.h +++ b/include/asm-i386/desc.h @@ -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); } diff --git a/include/asm-i386/mmu_context.h b/include/asm-i386/mmu_context.h index 769fad6d4f44..9b48c8b5e199 100644 --- a/include/asm-i386/mmu_context.h +++ b/include/asm-i386/mmu_context.h @@ -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) { /* -- 2.39.5