ia64/xen-unstable

changeset 12623:4f4d358aa5e4

merge with xen-unstable.hg
author awilliam@xenbuild.aw
date Tue Nov 28 10:37:36 2006 -0700 (2006-11-28)
parents 7e7846ea4ab3 7826e5482d42
children 6cfe32a69ac6
files patches/linux-2.6.16.29/blktap-aio-16_03_06.patch patches/linux-2.6.16.29/device_bind.patch patches/linux-2.6.16.29/fix-hz-suspend.patch patches/linux-2.6.16.29/fix-ide-cd-pio-mode.patch patches/linux-2.6.16.29/i386-mach-io-check-nmi.patch patches/linux-2.6.16.29/ipv6-no-autoconf.patch patches/linux-2.6.16.29/net-csum.patch patches/linux-2.6.16.29/net-gso-0-base.patch patches/linux-2.6.16.29/net-gso-1-check-dodgy.patch patches/linux-2.6.16.29/net-gso-2-checksum-fix.patch patches/linux-2.6.16.29/net-gso-3-fix-errorcheck.patch patches/linux-2.6.16.29/net-gso-4-kill-warnon.patch patches/linux-2.6.16.29/net-gso-5-rcv-mss.patch patches/linux-2.6.16.29/pci-mmconfig-fix-from-2.6.17.patch patches/linux-2.6.16.29/pmd-shared.patch patches/linux-2.6.16.29/rcu_needs_cpu.patch patches/linux-2.6.16.29/rename-TSS_sysenter_esp0-SYSENTER_stack_esp0.patch patches/linux-2.6.16.29/series patches/linux-2.6.16.29/smp-alts.patch patches/linux-2.6.16.29/tpm_plugin_2.6.17.patch patches/linux-2.6.16.29/x86-elfnote-as-preprocessor-macro.patch patches/linux-2.6.16.29/x86-increase-interrupt-vector-range.patch patches/linux-2.6.16.29/x86-put-note-sections-into-a-pt_note-segment-in-vmlinux.patch patches/linux-2.6.16.29/x86_64-put-note-sections-into-a-pt_note-segment-in-vmlinux.patch patches/linux-2.6.16.29/xen-hotplug.patch patches/linux-2.6.16.29/xenoprof-generic.patch tools/firmware/hvmloader/acpi/gen.c tools/firmware/hvmloader/acpi_madt.c xen/arch/x86/hvm/i8259.c
line diff
     1.1 --- a/.hgignore	Mon Nov 27 10:10:57 2006 -0700
     1.2 +++ b/.hgignore	Tue Nov 28 10:37:36 2006 -0700
     1.3 @@ -98,7 +98,6 @@
     1.4  ^tools/firmware/.*\.bin$
     1.5  ^tools/firmware/.*\.sym$
     1.6  ^tools/firmware/.*bios/.*bios.*\.txt$
     1.7 -^tools/firmware/hvmloader/acpi/acpigen$
     1.8  ^tools/firmware/hvmloader/hvmloader$
     1.9  ^tools/firmware/hvmloader/roms\.h$
    1.10  ^tools/firmware/rombios/BIOS-bochs-[^/]*$
     2.1 --- a/buildconfigs/mk.linux-2.6-xen	Mon Nov 27 10:10:57 2006 -0700
     2.2 +++ b/buildconfigs/mk.linux-2.6-xen	Tue Nov 28 10:37:36 2006 -0700
     2.3 @@ -1,5 +1,5 @@
     2.4  LINUX_SERIES = 2.6
     2.5 -LINUX_VER    = 2.6.16.29
     2.6 +LINUX_VER    = 2.6.16.32
     2.7  
     2.8  EXTRAVERSION ?= xen
     2.9  
     3.1 --- a/extras/mini-os/Makefile	Mon Nov 27 10:10:57 2006 -0700
     3.2 +++ b/extras/mini-os/Makefile	Tue Nov 28 10:37:36 2006 -0700
     3.3 @@ -55,9 +55,10 @@ EXTRA_SRC += arch/$(EXTRA_INC)
     3.4  endif
     3.5  
     3.6  ifeq ($(TARGET_ARCH),ia64)
     3.7 -CFLAGS += -mfixed-range=f12-f15,f32-f127
     3.8 -ASFLAGS += -x assembler-with-cpp -ansi -Wall
     3.9 -ASFLAGS += -mfixed-range=f12-f15,f32-f127
    3.10 +CFLAGS += -mfixed-range=f2-f5,f12-f15,f32-f127 -mconstant-gp
    3.11 +ASFLAGS += -x assembler-with-cpp -Wall
    3.12 +ASFLAGS += -mfixed-range=f2-f5,f12-f15,f32-f127 -fomit-frame-pointer
    3.13 +ASFLAGS += -fno-builtin -fno-common -fno-strict-aliasing -mconstant-gp
    3.14  ARCH_LINKS = IA64_LINKS		# Special link on ia64 needed
    3.15  define arch_links
    3.16  [ -e include/ia64/asm-xsi-offsets.h ] || ln -sf ../../../../xen/include/asm-ia64/asm-xsi-offsets.h include/ia64/asm-xsi-offsets.h
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/extras/mini-os/arch/x86/mm.c	Tue Nov 28 10:37:36 2006 -0700
     4.3 @@ -0,0 +1,428 @@
     4.4 +/* 
     4.5 + ****************************************************************************
     4.6 + * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
     4.7 + * (C) 2005 - Grzegorz Milos - Intel Research Cambridge
     4.8 + ****************************************************************************
     4.9 + *
    4.10 + *        File: mm.c
    4.11 + *      Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
    4.12 + *     Changes: Grzegorz Milos
    4.13 + *              
    4.14 + *        Date: Aug 2003, chages Aug 2005
    4.15 + * 
    4.16 + * Environment: Xen Minimal OS
    4.17 + * Description: memory management related functions
    4.18 + *              contains buddy page allocator from Xen.
    4.19 + *
    4.20 + ****************************************************************************
    4.21 + * Permission is hereby granted, free of charge, to any person obtaining a copy
    4.22 + * of this software and associated documentation files (the "Software"), to
    4.23 + * deal in the Software without restriction, including without limitation the
    4.24 + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
    4.25 + * sell copies of the Software, and to permit persons to whom the Software is
    4.26 + * furnished to do so, subject to the following conditions:
    4.27 + * 
    4.28 + * The above copyright notice and this permission notice shall be included in
    4.29 + * all copies or substantial portions of the Software.
    4.30 + * 
    4.31 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
    4.32 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
    4.33 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
    4.34 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
    4.35 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
    4.36 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
    4.37 + * DEALINGS IN THE SOFTWARE.
    4.38 + */
    4.39 +
    4.40 +#include <os.h>
    4.41 +#include <hypervisor.h>
    4.42 +#include <mm.h>
    4.43 +#include <types.h>
    4.44 +#include <lib.h>
    4.45 +#include <xmalloc.h>
    4.46 +
    4.47 +#ifdef MM_DEBUG
    4.48 +#define DEBUG(_f, _a...) \
    4.49 +    printk("MINI_OS(file=mm.c, line=%d) " _f "\n", __LINE__, ## _a)
    4.50 +#else
    4.51 +#define DEBUG(_f, _a...)    ((void)0)
    4.52 +#endif
    4.53 +
    4.54 +unsigned long *phys_to_machine_mapping;
    4.55 +extern char *stack;
    4.56 +extern void page_walk(unsigned long virt_addr);
    4.57 +
    4.58 +void new_pt_frame(unsigned long *pt_pfn, unsigned long prev_l_mfn, 
    4.59 +                                unsigned long offset, unsigned long level)
    4.60 +{   
    4.61 +    pgentry_t *tab = (pgentry_t *)start_info.pt_base;
    4.62 +    unsigned long pt_page = (unsigned long)pfn_to_virt(*pt_pfn); 
    4.63 +    unsigned long prot_e, prot_t, pincmd;
    4.64 +    mmu_update_t mmu_updates[1];
    4.65 +    struct mmuext_op pin_request;
    4.66 +    
    4.67 +    DEBUG("Allocating new L%d pt frame for pt_pfn=%lx, "
    4.68 +           "prev_l_mfn=%lx, offset=%lx", 
    4.69 +           level, *pt_pfn, prev_l_mfn, offset);
    4.70 +
    4.71 +    /* We need to clear the page, otherwise we might fail to map it
    4.72 +       as a page table page */
    4.73 +    memset((unsigned long*)pfn_to_virt(*pt_pfn), 0, PAGE_SIZE);  
    4.74 + 
    4.75 +    switch ( level )
    4.76 +    {
    4.77 +    case L1_FRAME:
    4.78 +         prot_e = L1_PROT;
    4.79 +         prot_t = L2_PROT;
    4.80 +         pincmd = MMUEXT_PIN_L1_TABLE;
    4.81 +         break;
    4.82 +#if defined(__x86_64__) || defined(CONFIG_X86_PAE)
    4.83 +    case L2_FRAME:
    4.84 +         prot_e = L2_PROT;
    4.85 +         prot_t = L3_PROT;
    4.86 +         pincmd = MMUEXT_PIN_L2_TABLE;
    4.87 +         break;
    4.88 +#endif
    4.89 +#if defined(__x86_64__)
    4.90 +    case L3_FRAME:
    4.91 +         prot_e = L3_PROT;
    4.92 +         prot_t = L4_PROT;
    4.93 +         pincmd = MMUEXT_PIN_L3_TABLE;
    4.94 +         break;
    4.95 +#endif
    4.96 +    default:
    4.97 +         printk("new_pt_frame() called with invalid level number %d\n", level);
    4.98 +         do_exit();
    4.99 +         break;
   4.100 +    }
   4.101 +
   4.102 +    /* Update the entry */
   4.103 +#if defined(__x86_64__)
   4.104 +    tab = pte_to_virt(tab[l4_table_offset(pt_page)]);
   4.105 +    tab = pte_to_virt(tab[l3_table_offset(pt_page)]);
   4.106 +#endif
   4.107 +#if defined(CONFIG_X86_PAE)
   4.108 +    tab = pte_to_virt(tab[l3_table_offset(pt_page)]);
   4.109 +#endif
   4.110 +
   4.111 +    mmu_updates[0].ptr = ((pgentry_t)tab[l2_table_offset(pt_page)] & PAGE_MASK) + 
   4.112 +                         sizeof(pgentry_t) * l1_table_offset(pt_page);
   4.113 +    mmu_updates[0].val = (pgentry_t)pfn_to_mfn(*pt_pfn) << PAGE_SHIFT | 
   4.114 +                         (prot_e & ~_PAGE_RW);
   4.115 +    if(HYPERVISOR_mmu_update(mmu_updates, 1, NULL, DOMID_SELF) < 0)
   4.116 +    {
   4.117 +         printk("PTE for new page table page could not be updated\n");
   4.118 +         do_exit();
   4.119 +    }
   4.120 +                        
   4.121 +    /* Pin the page to provide correct protection */
   4.122 +    pin_request.cmd = pincmd;
   4.123 +    pin_request.arg1.mfn = pfn_to_mfn(*pt_pfn);
   4.124 +    if(HYPERVISOR_mmuext_op(&pin_request, 1, NULL, DOMID_SELF) < 0)
   4.125 +    {
   4.126 +        printk("ERROR: pinning failed\n");
   4.127 +        do_exit();
   4.128 +    }
   4.129 +
   4.130 +    /* Now fill the new page table page with entries.
   4.131 +       Update the page directory as well. */
   4.132 +    mmu_updates[0].ptr = ((pgentry_t)prev_l_mfn << PAGE_SHIFT) + sizeof(pgentry_t) * offset;
   4.133 +    mmu_updates[0].val = (pgentry_t)pfn_to_mfn(*pt_pfn) << PAGE_SHIFT | prot_t;
   4.134 +    if(HYPERVISOR_mmu_update(mmu_updates, 1, NULL, DOMID_SELF) < 0) 
   4.135 +    {
   4.136 +       printk("ERROR: mmu_update failed\n");
   4.137 +       do_exit();
   4.138 +    }
   4.139 +
   4.140 +    *pt_pfn += 1;
   4.141 +}
   4.142 +
   4.143 +/* Checks if a pagetable frame is needed (if weren't allocated by Xen) */
   4.144 +static int need_pt_frame(unsigned long virt_address, int level)
   4.145 +{
   4.146 +    unsigned long hyp_virt_start = HYPERVISOR_VIRT_START;
   4.147 +#if defined(__x86_64__)
   4.148 +    unsigned long hyp_virt_end = HYPERVISOR_VIRT_END;
   4.149 +#else
   4.150 +    unsigned long hyp_virt_end = 0xffffffff;
   4.151 +#endif
   4.152 +
   4.153 +    /* In general frames will _not_ be needed if they were already
   4.154 +       allocated to map the hypervisor into our VA space */
   4.155 +#if defined(__x86_64__)
   4.156 +    if(level == L3_FRAME)
   4.157 +    {
   4.158 +        if(l4_table_offset(virt_address) >= 
   4.159 +           l4_table_offset(hyp_virt_start) &&
   4.160 +           l4_table_offset(virt_address) <= 
   4.161 +           l4_table_offset(hyp_virt_end))
   4.162 +            return 0;
   4.163 +        return 1;
   4.164 +    } else
   4.165 +#endif
   4.166 +
   4.167 +#if defined(__x86_64__) || defined(CONFIG_X86_PAE)
   4.168 +    if(level == L2_FRAME)
   4.169 +    {
   4.170 +#if defined(__x86_64__)
   4.171 +        if(l4_table_offset(virt_address) >= 
   4.172 +           l4_table_offset(hyp_virt_start) &&
   4.173 +           l4_table_offset(virt_address) <= 
   4.174 +           l4_table_offset(hyp_virt_end))
   4.175 +#endif
   4.176 +            if(l3_table_offset(virt_address) >= 
   4.177 +               l3_table_offset(hyp_virt_start) &&
   4.178 +               l3_table_offset(virt_address) <= 
   4.179 +               l3_table_offset(hyp_virt_end))
   4.180 +                return 0;
   4.181 +
   4.182 +        return 1;
   4.183 +    } else 
   4.184 +#endif /* defined(__x86_64__) || defined(CONFIG_X86_PAE) */
   4.185 +
   4.186 +    /* Always need l1 frames */
   4.187 +    if(level == L1_FRAME)
   4.188 +        return 1;
   4.189 +
   4.190 +    printk("ERROR: Unknown frame level %d, hypervisor %llx,%llx\n", 
   4.191 +        level, hyp_virt_start, hyp_virt_end);
   4.192 +    return -1;
   4.193 +}
   4.194 +
   4.195 +void build_pagetable(unsigned long *start_pfn, unsigned long *max_pfn)
   4.196 +{
   4.197 +    unsigned long start_address, end_address;
   4.198 +    unsigned long pfn_to_map, pt_pfn = *start_pfn;
   4.199 +    static mmu_update_t mmu_updates[L1_PAGETABLE_ENTRIES + 1];
   4.200 +    pgentry_t *tab = (pgentry_t *)start_info.pt_base, page;
   4.201 +    unsigned long mfn = pfn_to_mfn(virt_to_pfn(start_info.pt_base));
   4.202 +    unsigned long offset;
   4.203 +    int count = 0;
   4.204 +
   4.205 +    pfn_to_map = (start_info.nr_pt_frames - NOT_L1_FRAMES) * L1_PAGETABLE_ENTRIES;
   4.206 +
   4.207 +    if (*max_pfn >= virt_to_pfn(HYPERVISOR_VIRT_START))
   4.208 +    {
   4.209 +        printk("WARNING: Mini-OS trying to use Xen virtual space. "
   4.210 +               "Truncating memory from %dMB to ",
   4.211 +               ((unsigned long)pfn_to_virt(*max_pfn) - (unsigned long)&_text)>>20);
   4.212 +        *max_pfn = virt_to_pfn(HYPERVISOR_VIRT_START - PAGE_SIZE);
   4.213 +        printk("%dMB\n",
   4.214 +               ((unsigned long)pfn_to_virt(*max_pfn) - (unsigned long)&_text)>>20);
   4.215 +    }
   4.216 +
   4.217 +    start_address = (unsigned long)pfn_to_virt(pfn_to_map);
   4.218 +    end_address = (unsigned long)pfn_to_virt(*max_pfn);
   4.219 +
   4.220 +    /* We worked out the virtual memory range to map, now mapping loop */
   4.221 +    printk("Mapping memory range 0x%lx - 0x%lx\n", start_address, end_address);
   4.222 +
   4.223 +    while(start_address < end_address)
   4.224 +    {
   4.225 +        tab = (pgentry_t *)start_info.pt_base;
   4.226 +        mfn = pfn_to_mfn(virt_to_pfn(start_info.pt_base));
   4.227 +
   4.228 +#if defined(__x86_64__)
   4.229 +        offset = l4_table_offset(start_address);
   4.230 +        /* Need new L3 pt frame */
   4.231 +        if(!(start_address & L3_MASK)) 
   4.232 +            if(need_pt_frame(start_address, L3_FRAME)) 
   4.233 +                new_pt_frame(&pt_pfn, mfn, offset, L3_FRAME);
   4.234 +
   4.235 +        page = tab[offset];
   4.236 +        mfn = pte_to_mfn(page);
   4.237 +        tab = to_virt(mfn_to_pfn(mfn) << PAGE_SHIFT);
   4.238 +#endif
   4.239 +#if defined(__x86_64__) || defined(CONFIG_X86_PAE)
   4.240 +        offset = l3_table_offset(start_address);
   4.241 +        /* Need new L2 pt frame */
   4.242 +        if(!(start_address & L2_MASK))
   4.243 +            if(need_pt_frame(start_address, L2_FRAME))
   4.244 +                new_pt_frame(&pt_pfn, mfn, offset, L2_FRAME);
   4.245 +
   4.246 +        page = tab[offset];
   4.247 +        mfn = pte_to_mfn(page);
   4.248 +        tab = to_virt(mfn_to_pfn(mfn) << PAGE_SHIFT);
   4.249 +#endif
   4.250 +        offset = l2_table_offset(start_address);        
   4.251 +        /* Need new L1 pt frame */
   4.252 +        if(!(start_address & L1_MASK))
   4.253 +            if(need_pt_frame(start_address, L1_FRAME)) 
   4.254 +                new_pt_frame(&pt_pfn, mfn, offset, L1_FRAME);
   4.255 +
   4.256 +        page = tab[offset];
   4.257 +        mfn = pte_to_mfn(page);
   4.258 +        offset = l1_table_offset(start_address);
   4.259 +
   4.260 +        mmu_updates[count].ptr = ((pgentry_t)mfn << PAGE_SHIFT) + sizeof(pgentry_t) * offset;
   4.261 +        mmu_updates[count].val = (pgentry_t)pfn_to_mfn(pfn_to_map++) << PAGE_SHIFT | L1_PROT;
   4.262 +        count++;
   4.263 +        if (count == L1_PAGETABLE_ENTRIES || pfn_to_map == *max_pfn)
   4.264 +        {
   4.265 +            if(HYPERVISOR_mmu_update(mmu_updates, count, NULL, DOMID_SELF) < 0)
   4.266 +            {
   4.267 +                printk("PTE could not be updated\n");
   4.268 +                do_exit();
   4.269 +            }
   4.270 +            count = 0;
   4.271 +        }
   4.272 +        start_address += PAGE_SIZE;
   4.273 +    }
   4.274 +
   4.275 +    *start_pfn = pt_pfn;
   4.276 +}
   4.277 +
   4.278 +
   4.279 +void mem_test(unsigned long *start_add, unsigned long *end_add)
   4.280 +{
   4.281 +    unsigned long mask = 0x10000;
   4.282 +    unsigned long *pointer;
   4.283 +
   4.284 +    for(pointer = start_add; pointer < end_add; pointer++)
   4.285 +    {
   4.286 +        if(!(((unsigned long)pointer) & 0xfffff))
   4.287 +        {
   4.288 +            printk("Writing to %lx\n", pointer);
   4.289 +            page_walk((unsigned long)pointer);
   4.290 +        }
   4.291 +        *pointer = (unsigned long)pointer & ~mask;
   4.292 +    }
   4.293 +
   4.294 +    for(pointer = start_add; pointer < end_add; pointer++)
   4.295 +    {
   4.296 +        if(((unsigned long)pointer & ~mask) != *pointer)
   4.297 +            printk("Read error at 0x%lx. Read: 0x%lx, should read 0x%lx\n",
   4.298 +                (unsigned long)pointer, 
   4.299 +                *pointer, 
   4.300 +                ((unsigned long)pointer & ~mask));
   4.301 +    }
   4.302 +
   4.303 +}
   4.304 +
   4.305 +static pgentry_t *demand_map_pgt;
   4.306 +static void *demand_map_area_start;
   4.307 +
   4.308 +void arch_init_demand_mapping_area(unsigned long max_pfn)
   4.309 +{
   4.310 +    unsigned long mfn;
   4.311 +    pgentry_t *tab;
   4.312 +    unsigned long start_addr;
   4.313 +    unsigned long pt_pfn;
   4.314 +    unsigned offset;
   4.315 +
   4.316 +    /* Round up to four megs.  + 1024 rather than + 1023 since we want
   4.317 +       to be sure we don't end up in the same place we started. */
   4.318 +    max_pfn = (max_pfn + L1_PAGETABLE_ENTRIES) & ~(L1_PAGETABLE_ENTRIES - 1);
   4.319 +    if (max_pfn == 0 ||
   4.320 +            (unsigned long)pfn_to_virt(max_pfn + L1_PAGETABLE_ENTRIES) >=
   4.321 +            HYPERVISOR_VIRT_START) {
   4.322 +        printk("Too much memory; no room for demand map hole.\n");
   4.323 +        do_exit();
   4.324 +    }
   4.325 +
   4.326 +    demand_map_area_start = pfn_to_virt(max_pfn);
   4.327 +    printk("Demand map pfns start at %lx (%p).\n", max_pfn,
   4.328 +            demand_map_area_start);
   4.329 +    start_addr = (unsigned long)demand_map_area_start;
   4.330 +
   4.331 +    tab = (pgentry_t *)start_info.pt_base;
   4.332 +    mfn = virt_to_mfn(start_info.pt_base);
   4.333 +    pt_pfn = virt_to_pfn(alloc_page());
   4.334 +
   4.335 +#if defined(__x86_64__)
   4.336 +    offset = l4_table_offset(start_addr);
   4.337 +    if (!(tab[offset] & _PAGE_PRESENT)) {
   4.338 +        new_pt_frame(&pt_pfn, mfn, offset, L3_FRAME);
   4.339 +        pt_pfn = virt_to_pfn(alloc_page());
   4.340 +    }
   4.341 +    ASSERT(tab[offset] & _PAGE_PRESENT);
   4.342 +    mfn = pte_to_mfn(tab[offset]);
   4.343 +    tab = to_virt(mfn_to_pfn(mfn) << PAGE_SHIFT);
   4.344 +#endif
   4.345 +#if defined(__x86_64__) || defined(CONFIG_X86_PAE)
   4.346 +    offset = l3_table_offset(start_addr);
   4.347 +    if (!(tab[offset] & _PAGE_PRESENT)) {
   4.348 +        new_pt_frame(&pt_pfn, mfn, offset, L2_FRAME);
   4.349 +        pt_pfn = virt_to_pfn(alloc_page());
   4.350 +    }
   4.351 +    ASSERT(tab[offset] & _PAGE_PRESENT);
   4.352 +    mfn = pte_to_mfn(tab[offset]);
   4.353 +    tab = to_virt(mfn_to_pfn(mfn) << PAGE_SHIFT);
   4.354 +#endif
   4.355 +    offset = l2_table_offset(start_addr);
   4.356 +    if (tab[offset] & _PAGE_PRESENT) {
   4.357 +        printk("Demand map area already has a page table covering it?\n");
   4.358 +        BUG();
   4.359 +    }
   4.360 +    demand_map_pgt = pfn_to_virt(pt_pfn);
   4.361 +    new_pt_frame(&pt_pfn, mfn, offset, L1_FRAME);
   4.362 +    ASSERT(tab[offset] & _PAGE_PRESENT);
   4.363 +    printk("Initialised demand area.\n");
   4.364 +}
   4.365 +
   4.366 +void *map_frames(unsigned long *f, unsigned long n)
   4.367 +{
   4.368 +    unsigned long x;
   4.369 +    unsigned long y = 0;
   4.370 +    mmu_update_t mmu_updates[16];
   4.371 +    int rc;
   4.372 +
   4.373 +    if (n > 16) {
   4.374 +        printk("Tried to map too many (%ld) frames at once.\n", n);
   4.375 +        return NULL;
   4.376 +    }
   4.377 +
   4.378 +    /* Find a run of n contiguous frames */
   4.379 +    for (x = 0; x <= 1024 - n; x += y + 1) {
   4.380 +        for (y = 0; y < n; y++)
   4.381 +            if (demand_map_pgt[x+y] & _PAGE_PRESENT)
   4.382 +                break;
   4.383 +        if (y == n)
   4.384 +            break;
   4.385 +    }
   4.386 +    if (y != n) {
   4.387 +        printk("Failed to map %ld frames!\n", n);
   4.388 +        return NULL;
   4.389 +    }
   4.390 +
   4.391 +    /* Found it at x.  Map it in. */
   4.392 +    for (y = 0; y < n; y++) {
   4.393 +        mmu_updates[y].ptr = virt_to_mach(&demand_map_pgt[x + y]);
   4.394 +        mmu_updates[y].val = (f[y] << PAGE_SHIFT) | L1_PROT;
   4.395 +    }
   4.396 +
   4.397 +    rc = HYPERVISOR_mmu_update(mmu_updates, n, NULL, DOMID_SELF);
   4.398 +    if (rc < 0) {
   4.399 +        printk("Map %ld failed: %d.\n", n, rc);
   4.400 +        return NULL;
   4.401 +    } else {
   4.402 +        return (void *)(unsigned long)((unsigned long)demand_map_area_start +
   4.403 +                x * PAGE_SIZE);
   4.404 +    }
   4.405 +}
   4.406 +
   4.407 +void arch_init_mm(unsigned long* start_pfn_p, unsigned long* max_pfn_p)
   4.408 +{
   4.409 +
   4.410 +    unsigned long start_pfn, max_pfn;
   4.411 +
   4.412 +    printk("  _text:        %p\n", &_text);
   4.413 +    printk("  _etext:       %p\n", &_etext);
   4.414 +    printk("  _edata:       %p\n", &_edata);
   4.415 +    printk("  stack start:  %p\n", &stack);
   4.416 +    printk("  _end:         %p\n", &_end);
   4.417 +
   4.418 +    /* First page follows page table pages and 3 more pages (store page etc) */
   4.419 +    start_pfn = PFN_UP(to_phys(start_info.pt_base)) + 
   4.420 +                start_info.nr_pt_frames + 3;
   4.421 +    max_pfn = start_info.nr_pages;
   4.422 +   
   4.423 +    printk("  start_pfn:    %lx\n", start_pfn);
   4.424 +    printk("  max_pfn:      %lx\n", max_pfn);
   4.425 +
   4.426 +    build_pagetable(&start_pfn, &max_pfn);
   4.427 +
   4.428 +    *start_pfn_p = start_pfn;
   4.429 +    *max_pfn_p = max_pfn;
   4.430 +}
   4.431 +
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/extras/mini-os/arch/x86/sched.c	Tue Nov 28 10:37:36 2006 -0700
     5.3 @@ -0,0 +1,150 @@
     5.4 +/* 
     5.5 + ****************************************************************************
     5.6 + * (C) 2005 - Grzegorz Milos - Intel Research Cambridge
     5.7 + ****************************************************************************
     5.8 + *
     5.9 + *        File: sched.c
    5.10 + *      Author: Grzegorz Milos
    5.11 + *     Changes: Robert Kaiser
    5.12 + *              
    5.13 + *        Date: Aug 2005
    5.14 + * 
    5.15 + * Environment: Xen Minimal OS
    5.16 + * Description: simple scheduler for Mini-Os
    5.17 + *
    5.18 + * The scheduler is non-preemptive (cooperative), and schedules according 
    5.19 + * to Round Robin algorithm.
    5.20 + *
    5.21 + ****************************************************************************
    5.22 + * Permission is hereby granted, free of charge, to any person obtaining a copy
    5.23 + * of this software and associated documentation files (the "Software"), to
    5.24 + * deal in the Software without restriction, including without limitation the
    5.25 + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
    5.26 + * sell copies of the Software, and to permit persons to whom the Software is
    5.27 + * furnished to do so, subject to the following conditions:
    5.28 + * 
    5.29 + * The above copyright notice and this permission notice shall be included in
    5.30 + * all copies or substantial portions of the Software.
    5.31 + * 
    5.32 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
    5.33 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
    5.34 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
    5.35 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
    5.36 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
    5.37 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
    5.38 + * DEALINGS IN THE SOFTWARE.
    5.39 + */
    5.40 +
    5.41 +#include <os.h>
    5.42 +#include <hypervisor.h>
    5.43 +#include <time.h>
    5.44 +#include <mm.h>
    5.45 +#include <types.h>
    5.46 +#include <lib.h>
    5.47 +#include <xmalloc.h>
    5.48 +#include <list.h>
    5.49 +#include <sched.h>
    5.50 +#include <semaphore.h>
    5.51 +
    5.52 +
    5.53 +#ifdef SCHED_DEBUG
    5.54 +#define DEBUG(_f, _a...) \
    5.55 +    printk("MINI_OS(file=sched.c, line=%d) " _f "\n", __LINE__, ## _a)
    5.56 +#else
    5.57 +#define DEBUG(_f, _a...)    ((void)0)
    5.58 +#endif
    5.59 +
    5.60 +
    5.61 +void dump_stack(struct thread *thread)
    5.62 +{
    5.63 +    unsigned long *bottom = (unsigned long *)(thread->stack + 2*4*1024); 
    5.64 +    unsigned long *pointer = (unsigned long *)thread->sp;
    5.65 +    int count;
    5.66 +    if(thread == current)
    5.67 +    {
    5.68 +#ifdef __i386__    
    5.69 +        asm("movl %%esp,%0"
    5.70 +            : "=r"(pointer));
    5.71 +#else
    5.72 +        asm("movq %%rsp,%0"
    5.73 +            : "=r"(pointer));
    5.74 +#endif
    5.75 +    }
    5.76 +    printk("The stack for \"%s\"\n", thread->name);
    5.77 +    for(count = 0; count < 25 && pointer < bottom; count ++)
    5.78 +    {
    5.79 +        printk("[0x%lx] 0x%lx\n", pointer, *pointer);
    5.80 +        pointer++;
    5.81 +    }
    5.82 +    
    5.83 +    if(pointer < bottom) printk(" ... continues.\n");
    5.84 +}
    5.85 +
    5.86 +/* Gets run when a new thread is scheduled the first time ever, 
    5.87 +   defined in x86_[32/64].S */
    5.88 +extern void thread_starter(void);
    5.89 +
    5.90 +/* Pushes the specified value onto the stack of the specified thread */
    5.91 +static void stack_push(struct thread *thread, unsigned long value)
    5.92 +{
    5.93 +    thread->sp -= sizeof(unsigned long);
    5.94 +    *((unsigned long *)thread->sp) = value;
    5.95 +}
    5.96 +
    5.97 +struct thread* create_thread(char *name, void (*function)(void *), void *data)
    5.98 +{
    5.99 +    struct thread *thread;
   5.100 +    unsigned long flags;
   5.101 +    
   5.102 +    thread = xmalloc(struct thread);
   5.103 +    /* Allocate 2 pages for stack, stack will be 2pages aligned */
   5.104 +    thread->stack = (char *)alloc_pages(1);
   5.105 +    thread->name = name;
   5.106 +    printk("Thread \"%s\": pointer: 0x%lx, stack: 0x%lx\n", name, thread, 
   5.107 +            thread->stack);
   5.108 +    
   5.109 +    thread->sp = (unsigned long)thread->stack + 4096 * 2;
   5.110 +    /* Save pointer to the thread on the stack, used by current macro */
   5.111 +    *((unsigned long *)thread->stack) = (unsigned long)thread;
   5.112 +    
   5.113 +    stack_push(thread, (unsigned long) function);
   5.114 +    stack_push(thread, (unsigned long) data);
   5.115 +    thread->ip = (unsigned long) thread_starter;
   5.116 +     
   5.117 +    /* Not runable, not exited, not sleeping */
   5.118 +    thread->flags = 0;
   5.119 +    thread->wakeup_time = 0LL;
   5.120 +    set_runnable(thread);
   5.121 +    local_irq_save(flags);
   5.122 +    if(idle_thread != NULL) {
   5.123 +        list_add_tail(&thread->thread_list, &idle_thread->thread_list); 
   5.124 +    } else if(function != idle_thread_fn)
   5.125 +    {
   5.126 +        printk("BUG: Not allowed to create thread before initialising scheduler.\n");
   5.127 +        BUG();
   5.128 +    }
   5.129 +    local_irq_restore(flags);
   5.130 +    return thread;
   5.131 +}
   5.132 +
   5.133 +
   5.134 +void run_idle_thread(void)
   5.135 +{
   5.136 +    /* Switch stacks and run the thread */ 
   5.137 +#if defined(__i386__)
   5.138 +    __asm__ __volatile__("mov %0,%%esp\n\t"
   5.139 +                         "push %1\n\t" 
   5.140 +                         "ret"                                            
   5.141 +                         :"=m" (idle_thread->sp)
   5.142 +                         :"m" (idle_thread->ip));                          
   5.143 +#elif defined(__x86_64__)
   5.144 +    __asm__ __volatile__("mov %0,%%rsp\n\t"
   5.145 +                         "push %1\n\t" 
   5.146 +                         "ret"                                            
   5.147 +                         :"=m" (idle_thread->sp)
   5.148 +                         :"m" (idle_thread->ip));                                                    
   5.149 +#endif
   5.150 +}
   5.151 +
   5.152 +
   5.153 +
     6.1 --- a/extras/mini-os/events.c	Mon Nov 27 10:10:57 2006 -0700
     6.2 +++ b/extras/mini-os/events.c	Tue Nov 28 10:37:36 2006 -0700
     6.3 @@ -35,6 +35,21 @@ typedef struct _ev_action_t {
     6.4  static ev_action_t ev_actions[NR_EVS];
     6.5  void default_handler(evtchn_port_t port, struct pt_regs *regs, void *data);
     6.6  
     6.7 +void unbind_all_ports(void)
     6.8 +{
     6.9 +    int i;
    6.10 +
    6.11 +	for(i=0;i<NR_EVS;i++)
    6.12 +	{
    6.13 +		if(ev_actions[i].handler != default_handler)
    6.14 +		{
    6.15 +			struct evtchn_close close;
    6.16 +			mask_evtchn(i);
    6.17 +			close.port = i;
    6.18 +			HYPERVISOR_event_channel_op(EVTCHNOP_close, &close);
    6.19 +		}
    6.20 +	}
    6.21 +}
    6.22  
    6.23  /*
    6.24   * Demux events to different handlers.
     7.1 --- a/extras/mini-os/include/mm.h	Mon Nov 27 10:10:57 2006 -0700
     7.2 +++ b/extras/mini-os/include/mm.h	Tue Nov 28 10:37:36 2006 -0700
     7.3 @@ -29,182 +29,15 @@
     7.4  #include <xen/arch-x86_32.h>
     7.5  #elif defined(__x86_64__)
     7.6  #include <xen/arch-x86_64.h>
     7.7 +#elif defined(__ia64__)
     7.8 +#include <xen/arch-ia64.h>
     7.9  #else
    7.10  #error "Unsupported architecture"
    7.11  #endif
    7.12  
    7.13  #include <lib.h>
    7.14 -
    7.15 -#define L1_FRAME                1
    7.16 -#define L2_FRAME                2
    7.17 -#define L3_FRAME                3
    7.18 -
    7.19 -#define L1_PAGETABLE_SHIFT      12
    7.20 -
    7.21 -#if defined(__i386__)
    7.22 -
    7.23 -#if !defined(CONFIG_X86_PAE)
    7.24 -
    7.25 -#define L2_PAGETABLE_SHIFT      22
    7.26 -
    7.27 -#define L1_PAGETABLE_ENTRIES    1024
    7.28 -#define L2_PAGETABLE_ENTRIES    1024
    7.29 -
    7.30 -#define PADDR_BITS              32
    7.31 -#define PADDR_MASK              (~0UL)
    7.32 -
    7.33 -#define NOT_L1_FRAMES           1
    7.34 -#define PRIpte "08lx"
    7.35 -typedef unsigned long pgentry_t;
    7.36 -
    7.37 -#else /* defined(CONFIG_X86_PAE) */
    7.38 -
    7.39 -#define L2_PAGETABLE_SHIFT      21
    7.40 -#define L3_PAGETABLE_SHIFT      30
    7.41 -
    7.42 -#define L1_PAGETABLE_ENTRIES    512
    7.43 -#define L2_PAGETABLE_ENTRIES    512
    7.44 -#define L3_PAGETABLE_ENTRIES    4
    7.45 -
    7.46 -#define PADDR_BITS              44
    7.47 -#define PADDR_MASK              ((1ULL << PADDR_BITS)-1)
    7.48 -
    7.49 -#define L2_MASK  ((1UL << L3_PAGETABLE_SHIFT) - 1)
    7.50 -
    7.51 -/*
    7.52 - * If starting from virtual address greater than 0xc0000000,
    7.53 - * this value will be 2 to account for final mid-level page
    7.54 - * directory which is always mapped in at this location.
    7.55 - */
    7.56 -#define NOT_L1_FRAMES           3
    7.57 -#define PRIpte "016llx"
    7.58 -typedef uint64_t pgentry_t;
    7.59 -
    7.60 -#endif /* !defined(CONFIG_X86_PAE) */
    7.61 -
    7.62 -#elif defined(__x86_64__)
    7.63 -
    7.64 -#define L2_PAGETABLE_SHIFT      21
    7.65 -#define L3_PAGETABLE_SHIFT      30
    7.66 -#define L4_PAGETABLE_SHIFT      39
    7.67 -
    7.68 -#define L1_PAGETABLE_ENTRIES    512
    7.69 -#define L2_PAGETABLE_ENTRIES    512
    7.70 -#define L3_PAGETABLE_ENTRIES    512
    7.71 -#define L4_PAGETABLE_ENTRIES    512
    7.72 -
    7.73 -/* These are page-table limitations. Current CPUs support only 40-bit phys. */
    7.74 -#define PADDR_BITS              52
    7.75 -#define VADDR_BITS              48
    7.76 -#define PADDR_MASK              ((1UL << PADDR_BITS)-1)
    7.77 -#define VADDR_MASK              ((1UL << VADDR_BITS)-1)
    7.78 -
    7.79 -#define L2_MASK  ((1UL << L3_PAGETABLE_SHIFT) - 1)
    7.80 -#define L3_MASK  ((1UL << L4_PAGETABLE_SHIFT) - 1)
    7.81 -
    7.82 -#define NOT_L1_FRAMES           3
    7.83 -#define PRIpte "016lx"
    7.84 -typedef unsigned long pgentry_t;
    7.85 -
    7.86 -#endif
    7.87 -
    7.88 -#define L1_MASK  ((1UL << L2_PAGETABLE_SHIFT) - 1)
    7.89 +#include <arch_mm.h>
    7.90  
    7.91 -/* Given a virtual address, get an entry offset into a page table. */
    7.92 -#define l1_table_offset(_a) \
    7.93 -  (((_a) >> L1_PAGETABLE_SHIFT) & (L1_PAGETABLE_ENTRIES - 1))
    7.94 -#define l2_table_offset(_a) \
    7.95 -  (((_a) >> L2_PAGETABLE_SHIFT) & (L2_PAGETABLE_ENTRIES - 1))
    7.96 -#if defined(__x86_64__) || defined(CONFIG_X86_PAE)
    7.97 -#define l3_table_offset(_a) \
    7.98 -  (((_a) >> L3_PAGETABLE_SHIFT) & (L3_PAGETABLE_ENTRIES - 1))
    7.99 -#endif
   7.100 -#if defined(__x86_64__)
   7.101 -#define l4_table_offset(_a) \
   7.102 -  (((_a) >> L4_PAGETABLE_SHIFT) & (L4_PAGETABLE_ENTRIES - 1))
   7.103 -#endif
   7.104 -
   7.105 -#define _PAGE_PRESENT  0x001UL
   7.106 -#define _PAGE_RW       0x002UL
   7.107 -#define _PAGE_USER     0x004UL
   7.108 -#define _PAGE_PWT      0x008UL
   7.109 -#define _PAGE_PCD      0x010UL
   7.110 -#define _PAGE_ACCESSED 0x020UL
   7.111 -#define _PAGE_DIRTY    0x040UL
   7.112 -#define _PAGE_PAT      0x080UL
   7.113 -#define _PAGE_PSE      0x080UL
   7.114 -#define _PAGE_GLOBAL   0x100UL
   7.115 -
   7.116 -#if defined(__i386__)
   7.117 -#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED)
   7.118 -#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY |_PAGE_USER)
   7.119 -#if defined(CONFIG_X86_PAE)
   7.120 -#define L3_PROT (_PAGE_PRESENT)
   7.121 -#endif /* CONFIG_X86_PAE */
   7.122 -#elif defined(__x86_64__)
   7.123 -#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_USER)
   7.124 -#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
   7.125 -#define L3_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
   7.126 -#define L4_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
   7.127 -#endif /* __i386__ || __x86_64__ */
   7.128 -
   7.129 -#ifndef CONFIG_X86_PAE
   7.130 -#define PAGE_SIZE       (1UL << L1_PAGETABLE_SHIFT)
   7.131 -#else
   7.132 -#define PAGE_SIZE       (1ULL << L1_PAGETABLE_SHIFT)
   7.133 -#endif
   7.134 -#define PAGE_SHIFT      L1_PAGETABLE_SHIFT
   7.135 -#define PAGE_MASK       (~(PAGE_SIZE-1))
   7.136 -
   7.137 -#define PFN_UP(x)	(((x) + PAGE_SIZE-1) >> L1_PAGETABLE_SHIFT)
   7.138 -#define PFN_DOWN(x)	((x) >> L1_PAGETABLE_SHIFT)
   7.139 -#define PFN_PHYS(x)	((x) << L1_PAGETABLE_SHIFT)
   7.140 -
   7.141 -/* to align the pointer to the (next) page boundary */
   7.142 -#define PAGE_ALIGN(addr)        (((addr)+PAGE_SIZE-1)&PAGE_MASK)
   7.143 -
   7.144 -/* Definitions for machine and pseudophysical addresses. */
   7.145 -#ifdef CONFIG_X86_PAE
   7.146 -typedef unsigned long long paddr_t;
   7.147 -typedef unsigned long long maddr_t;
   7.148 -#else
   7.149 -typedef unsigned long paddr_t;
   7.150 -typedef unsigned long maddr_t;
   7.151 -#endif
   7.152 -
   7.153 -extern unsigned long *phys_to_machine_mapping;
   7.154 -extern char _text, _etext, _edata, _end;
   7.155 -#define pfn_to_mfn(_pfn) (phys_to_machine_mapping[(_pfn)])
   7.156 -static __inline__ maddr_t phys_to_machine(paddr_t phys)
   7.157 -{
   7.158 -	maddr_t machine = pfn_to_mfn(phys >> PAGE_SHIFT);
   7.159 -	machine = (machine << PAGE_SHIFT) | (phys & ~PAGE_MASK);
   7.160 -	return machine;
   7.161 -}
   7.162 -
   7.163 -#define mfn_to_pfn(_mfn) (machine_to_phys_mapping[(_mfn)])
   7.164 -static __inline__ paddr_t machine_to_phys(maddr_t machine)
   7.165 -{
   7.166 -	paddr_t phys = mfn_to_pfn(machine >> PAGE_SHIFT);
   7.167 -	phys = (phys << PAGE_SHIFT) | (machine & ~PAGE_MASK);
   7.168 -	return phys;
   7.169 -}
   7.170 -
   7.171 -#define VIRT_START                 ((unsigned long)&_text)
   7.172 -
   7.173 -#define to_phys(x)                 ((unsigned long)(x)-VIRT_START)
   7.174 -#define to_virt(x)                 ((void *)((unsigned long)(x)+VIRT_START))
   7.175 -
   7.176 -#define virt_to_pfn(_virt)         (PFN_DOWN(to_phys(_virt)))
   7.177 -#define virt_to_mfn(_virt)         (pfn_to_mfn(virt_to_pfn(_virt)))
   7.178 -#define mach_to_virt(_mach)        (to_virt(machine_to_phys(_mach)))
   7.179 -#define virt_to_mach(_virt)        (phys_to_machine(to_phys(_virt)))
   7.180 -#define mfn_to_virt(_mfn)          (to_virt(mfn_to_pfn(_mfn) << PAGE_SHIFT))
   7.181 -#define pfn_to_virt(_pfn)          (to_virt((_pfn) << PAGE_SHIFT))
   7.182 -
   7.183 -/* Pagetable walking. */
   7.184 -#define pte_to_mfn(_pte)           (((_pte) & (PADDR_MASK&PAGE_MASK)) >> L1_PAGETABLE_SHIFT)
   7.185 -#define pte_to_virt(_pte)          to_virt(mfn_to_pfn(pte_to_mfn(_pte)) << PAGE_SHIFT)
   7.186  
   7.187  void init_mm(void);
   7.188  unsigned long alloc_pages(int order);
   7.189 @@ -220,6 +53,8 @@ static __inline__ int get_order(unsigned
   7.190      return order;
   7.191  }
   7.192  
   7.193 +void arch_init_demand_mapping_area(unsigned long max_pfn);
   7.194 +void arch_init_mm(unsigned long* start_pfn_p, unsigned long* max_pfn_p);
   7.195  
   7.196  void *map_frames(unsigned long *f, unsigned long n);
   7.197  
     8.1 --- a/extras/mini-os/include/sched.h	Mon Nov 27 10:10:57 2006 -0700
     8.2 +++ b/extras/mini-os/include/sched.h	Tue Nov 28 10:37:36 2006 -0700
     8.3 @@ -3,36 +3,40 @@
     8.4  
     8.5  #include <list.h>
     8.6  #include <time.h>
     8.7 +#include <arch_sched.h>
     8.8  
     8.9  struct thread
    8.10  {
    8.11      char *name;
    8.12      char *stack;
    8.13 +#if !defined(__ia64__)
    8.14      unsigned long sp;  /* Stack pointer */
    8.15      unsigned long ip;  /* Instruction pointer */
    8.16 +#else /* !defined(__ia64__) */
    8.17 +    thread_regs_t regs;
    8.18 +#endif /* !defined(__ia64__) */
    8.19      struct list_head thread_list;
    8.20      u32 flags;
    8.21      s_time_t wakeup_time;
    8.22  };
    8.23  
    8.24 +extern struct thread *idle_thread;
    8.25 +void idle_thread_fn(void *unused);
    8.26  
    8.27 +#define RUNNABLE_FLAG   0x00000001
    8.28 +
    8.29 +#define is_runnable(_thread)    (_thread->flags & RUNNABLE_FLAG)
    8.30 +#define set_runnable(_thread)   (_thread->flags |= RUNNABLE_FLAG)
    8.31 +#define clear_runnable(_thread) (_thread->flags &= ~RUNNABLE_FLAG)
    8.32 +
    8.33 +#define switch_threads(prev, next) arch_switch_threads(prev, next)
    8.34 + 
    8.35  
    8.36  void init_sched(void);
    8.37  void run_idle_thread(void);
    8.38  struct thread* create_thread(char *name, void (*function)(void *), void *data);
    8.39  void schedule(void);
    8.40  
    8.41 -static inline struct thread* get_current(void)
    8.42 -{
    8.43 -    struct thread **current;
    8.44 -#ifdef __i386__    
    8.45 -    __asm__("andl %%esp,%0; ":"=r" (current) : "r" (~8191UL));
    8.46 -#else
    8.47 -    __asm__("andq %%rsp,%0; ":"=r" (current) : "r" (~8191UL));
    8.48 -#endif 
    8.49 -    return *current;
    8.50 -}
    8.51 -          
    8.52  #define current get_current()
    8.53  
    8.54  
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/extras/mini-os/include/x86/arch_mm.h	Tue Nov 28 10:37:36 2006 -0700
     9.3 @@ -0,0 +1,209 @@
     9.4 +/* -*-  Mode:C; c-basic-offset:4; tab-width:4 -*-
     9.5 + *
     9.6 + * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
     9.7 + * Copyright (c) 2005, Keir A Fraser
     9.8 + *
     9.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy
    9.10 + * of this software and associated documentation files (the "Software"), to
    9.11 + * deal in the Software without restriction, including without limitation the
    9.12 + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
    9.13 + * sell copies of the Software, and to permit persons to whom the Software is
    9.14 + * furnished to do so, subject to the following conditions:
    9.15 + * 
    9.16 + * The above copyright notice and this permission notice shall be included in
    9.17 + * all copies or substantial portions of the Software.
    9.18 + * 
    9.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
    9.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
    9.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
    9.22 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
    9.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
    9.24 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
    9.25 + * DEALINGS IN THE SOFTWARE.
    9.26 + */
    9.27 +
    9.28 +#ifndef _ARCH_MM_H_
    9.29 +#define _ARCH_MM_H_
    9.30 +
    9.31 +#if defined(__i386__)
    9.32 +#include <xen/arch-x86_32.h>
    9.33 +#elif defined(__x86_64__)
    9.34 +#include <xen/arch-x86_64.h>
    9.35 +#else
    9.36 +#error "Unsupported architecture"
    9.37 +#endif
    9.38 +
    9.39 +#define L1_FRAME                1
    9.40 +#define L2_FRAME                2
    9.41 +#define L3_FRAME                3
    9.42 +
    9.43 +#define L1_PAGETABLE_SHIFT      12
    9.44 +
    9.45 +#if defined(__i386__)
    9.46 +
    9.47 +#if !defined(CONFIG_X86_PAE)
    9.48 +
    9.49 +#define L2_PAGETABLE_SHIFT      22
    9.50 +
    9.51 +#define L1_PAGETABLE_ENTRIES    1024
    9.52 +#define L2_PAGETABLE_ENTRIES    1024
    9.53 +
    9.54 +#define PADDR_BITS              32
    9.55 +#define PADDR_MASK              (~0UL)
    9.56 +
    9.57 +#define NOT_L1_FRAMES           1
    9.58 +#define PRIpte "08lx"
    9.59 +typedef unsigned long pgentry_t;
    9.60 +
    9.61 +#else /* defined(CONFIG_X86_PAE) */
    9.62 +
    9.63 +#define L2_PAGETABLE_SHIFT      21
    9.64 +#define L3_PAGETABLE_SHIFT      30
    9.65 +
    9.66 +#define L1_PAGETABLE_ENTRIES    512
    9.67 +#define L2_PAGETABLE_ENTRIES    512
    9.68 +#define L3_PAGETABLE_ENTRIES    4
    9.69 +
    9.70 +#define PADDR_BITS              44
    9.71 +#define PADDR_MASK              ((1ULL << PADDR_BITS)-1)
    9.72 +
    9.73 +#define L2_MASK  ((1UL << L3_PAGETABLE_SHIFT) - 1)
    9.74 +
    9.75 +/*
    9.76 + * If starting from virtual address greater than 0xc0000000,
    9.77 + * this value will be 2 to account for final mid-level page
    9.78 + * directory which is always mapped in at this location.
    9.79 + */
    9.80 +#define NOT_L1_FRAMES           3
    9.81 +#define PRIpte "016llx"
    9.82 +typedef uint64_t pgentry_t;
    9.83 +
    9.84 +#endif /* !defined(CONFIG_X86_PAE) */
    9.85 +
    9.86 +#elif defined(__x86_64__)
    9.87 +
    9.88 +#define L2_PAGETABLE_SHIFT      21
    9.89 +#define L3_PAGETABLE_SHIFT      30
    9.90 +#define L4_PAGETABLE_SHIFT      39
    9.91 +
    9.92 +#define L1_PAGETABLE_ENTRIES    512
    9.93 +#define L2_PAGETABLE_ENTRIES    512
    9.94 +#define L3_PAGETABLE_ENTRIES    512
    9.95 +#define L4_PAGETABLE_ENTRIES    512
    9.96 +
    9.97 +/* These are page-table limitations. Current CPUs support only 40-bit phys. */
    9.98 +#define PADDR_BITS              52
    9.99 +#define VADDR_BITS              48
   9.100 +#define PADDR_MASK              ((1UL << PADDR_BITS)-1)
   9.101 +#define VADDR_MASK              ((1UL << VADDR_BITS)-1)
   9.102 +
   9.103 +#define L2_MASK  ((1UL << L3_PAGETABLE_SHIFT) - 1)
   9.104 +#define L3_MASK  ((1UL << L4_PAGETABLE_SHIFT) - 1)
   9.105 +
   9.106 +#define NOT_L1_FRAMES           3
   9.107 +#define PRIpte "016lx"
   9.108 +typedef unsigned long pgentry_t;
   9.109 +
   9.110 +#endif
   9.111 +
   9.112 +#define L1_MASK  ((1UL << L2_PAGETABLE_SHIFT) - 1)
   9.113 +
   9.114 +/* Given a virtual address, get an entry offset into a page table. */
   9.115 +#define l1_table_offset(_a) \
   9.116 +  (((_a) >> L1_PAGETABLE_SHIFT) & (L1_PAGETABLE_ENTRIES - 1))
   9.117 +#define l2_table_offset(_a) \
   9.118 +  (((_a) >> L2_PAGETABLE_SHIFT) & (L2_PAGETABLE_ENTRIES - 1))
   9.119 +#if defined(__x86_64__) || defined(CONFIG_X86_PAE)
   9.120 +#define l3_table_offset(_a) \
   9.121 +  (((_a) >> L3_PAGETABLE_SHIFT) & (L3_PAGETABLE_ENTRIES - 1))
   9.122 +#endif
   9.123 +#if defined(__x86_64__)
   9.124 +#define l4_table_offset(_a) \
   9.125 +  (((_a) >> L4_PAGETABLE_SHIFT) & (L4_PAGETABLE_ENTRIES - 1))
   9.126 +#endif
   9.127 +
   9.128 +#define _PAGE_PRESENT  0x001UL
   9.129 +#define _PAGE_RW       0x002UL
   9.130 +#define _PAGE_USER     0x004UL
   9.131 +#define _PAGE_PWT      0x008UL
   9.132 +#define _PAGE_PCD      0x010UL
   9.133 +#define _PAGE_ACCESSED 0x020UL
   9.134 +#define _PAGE_DIRTY    0x040UL
   9.135 +#define _PAGE_PAT      0x080UL
   9.136 +#define _PAGE_PSE      0x080UL
   9.137 +#define _PAGE_GLOBAL   0x100UL
   9.138 +
   9.139 +#if defined(__i386__)
   9.140 +#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED)
   9.141 +#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY |_PAGE_USER)
   9.142 +#if defined(CONFIG_X86_PAE)
   9.143 +#define L3_PROT (_PAGE_PRESENT)
   9.144 +#endif /* CONFIG_X86_PAE */
   9.145 +#elif defined(__x86_64__)
   9.146 +#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_USER)
   9.147 +#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
   9.148 +#define L3_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
   9.149 +#define L4_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
   9.150 +#endif /* __i386__ || __x86_64__ */
   9.151 +
   9.152 +#ifndef CONFIG_X86_PAE
   9.153 +#define PAGE_SIZE       (1UL << L1_PAGETABLE_SHIFT)
   9.154 +#else
   9.155 +#define PAGE_SIZE       (1ULL << L1_PAGETABLE_SHIFT)
   9.156 +#endif
   9.157 +#define PAGE_SHIFT      L1_PAGETABLE_SHIFT
   9.158 +#define PAGE_MASK       (~(PAGE_SIZE-1))
   9.159 +
   9.160 +#define PFN_UP(x)	(((x) + PAGE_SIZE-1) >> L1_PAGETABLE_SHIFT)
   9.161 +#define PFN_DOWN(x)	((x) >> L1_PAGETABLE_SHIFT)
   9.162 +#define PFN_PHYS(x)	((x) << L1_PAGETABLE_SHIFT)
   9.163 +#define PHYS_PFN(x)	((x) >> L1_PAGETABLE_SHIFT)
   9.164 +
   9.165 +/* to align the pointer to the (next) page boundary */
   9.166 +#define PAGE_ALIGN(addr)        (((addr)+PAGE_SIZE-1)&PAGE_MASK)
   9.167 +
   9.168 +/* Definitions for machine and pseudophysical addresses. */
   9.169 +#ifdef CONFIG_X86_PAE
   9.170 +typedef unsigned long long paddr_t;
   9.171 +typedef unsigned long long maddr_t;
   9.172 +#else
   9.173 +typedef unsigned long paddr_t;
   9.174 +typedef unsigned long maddr_t;
   9.175 +#endif
   9.176 +
   9.177 +extern unsigned long *phys_to_machine_mapping;
   9.178 +extern char _text, _etext, _edata, _end;
   9.179 +#define pfn_to_mfn(_pfn) (phys_to_machine_mapping[(_pfn)])
   9.180 +static __inline__ maddr_t phys_to_machine(paddr_t phys)
   9.181 +{
   9.182 +	maddr_t machine = pfn_to_mfn(phys >> PAGE_SHIFT);
   9.183 +	machine = (machine << PAGE_SHIFT) | (phys & ~PAGE_MASK);
   9.184 +	return machine;
   9.185 +}
   9.186 +
   9.187 +#define mfn_to_pfn(_mfn) (machine_to_phys_mapping[(_mfn)])
   9.188 +static __inline__ paddr_t machine_to_phys(maddr_t machine)
   9.189 +{
   9.190 +	paddr_t phys = mfn_to_pfn(machine >> PAGE_SHIFT);
   9.191 +	phys = (phys << PAGE_SHIFT) | (machine & ~PAGE_MASK);
   9.192 +	return phys;
   9.193 +}
   9.194 +
   9.195 +#define VIRT_START                 ((unsigned long)&_text)
   9.196 +
   9.197 +#define to_phys(x)                 ((unsigned long)(x)-VIRT_START)
   9.198 +#define to_virt(x)                 ((void *)((unsigned long)(x)+VIRT_START))
   9.199 +
   9.200 +#define virt_to_pfn(_virt)         (PFN_DOWN(to_phys(_virt)))
   9.201 +#define virt_to_mfn(_virt)         (pfn_to_mfn(virt_to_pfn(_virt)))
   9.202 +#define mach_to_virt(_mach)        (to_virt(machine_to_phys(_mach)))
   9.203 +#define virt_to_mach(_virt)        (phys_to_machine(to_phys(_virt)))
   9.204 +#define mfn_to_virt(_mfn)          (to_virt(mfn_to_pfn(_mfn) << PAGE_SHIFT))
   9.205 +#define pfn_to_virt(_pfn)          (to_virt((_pfn) << PAGE_SHIFT))
   9.206 +
   9.207 +/* Pagetable walking. */
   9.208 +#define pte_to_mfn(_pte)           (((_pte) & (PADDR_MASK&PAGE_MASK)) >> L1_PAGETABLE_SHIFT)
   9.209 +#define pte_to_virt(_pte)          to_virt(mfn_to_pfn(pte_to_mfn(_pte)) << PAGE_SHIFT)
   9.210 +
   9.211 +
   9.212 +#endif /* _ARCH_MM_H_ */
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/extras/mini-os/include/x86/arch_sched.h	Tue Nov 28 10:37:36 2006 -0700
    10.3 @@ -0,0 +1,58 @@
    10.4 +
    10.5 +#ifndef __ARCH_SCHED_H__
    10.6 +#define __ARCH_SCHED_H__
    10.7 +
    10.8 +
    10.9 +static inline struct thread* get_current(void)
   10.10 +{
   10.11 +    struct thread **current;
   10.12 +#ifdef __i386__    
   10.13 +    __asm__("andl %%esp,%0; ":"=r" (current) : "r" (~8191UL));
   10.14 +#else
   10.15 +    __asm__("andq %%rsp,%0; ":"=r" (current) : "r" (~8191UL));
   10.16 +#endif 
   10.17 +    return *current;
   10.18 +}
   10.19 +
   10.20 +#ifdef __i386__
   10.21 +#define arch_switch_threads(prev, next) do {                            \
   10.22 +    unsigned long esi,edi;                                              \
   10.23 +    __asm__ __volatile__("pushfl\n\t"                                   \
   10.24 +                         "pushl %%ebp\n\t"                              \
   10.25 +                         "movl %%esp,%0\n\t"         /* save ESP */     \
   10.26 +                         "movl %4,%%esp\n\t"        /* restore ESP */   \
   10.27 +                         "movl $1f,%1\n\t"          /* save EIP */      \
   10.28 +                         "pushl %5\n\t"             /* restore EIP */   \
   10.29 +                         "ret\n\t"                                      \
   10.30 +                         "1:\t"                                         \
   10.31 +                         "popl %%ebp\n\t"                               \
   10.32 +                         "popfl"                                        \
   10.33 +                         :"=m" (prev->sp),"=m" (prev->ip),            \
   10.34 +                          "=S" (esi),"=D" (edi)             \
   10.35 +                         :"m" (next->sp),"m" (next->ip),              \
   10.36 +                          "2" (prev), "d" (next));                      \
   10.37 +} while (0)
   10.38 +#elif __x86_64__
   10.39 +#define arch_switch_threads(prev, next) do {                                 \
   10.40 +    unsigned long rsi,rdi;                                              \
   10.41 +    __asm__ __volatile__("pushfq\n\t"                                   \
   10.42 +                         "pushq %%rbp\n\t"                              \
   10.43 +                         "movq %%rsp,%0\n\t"         /* save RSP */     \
   10.44 +                         "movq %4,%%rsp\n\t"        /* restore RSP */   \
   10.45 +                         "movq $1f,%1\n\t"          /* save RIP */      \
   10.46 +                         "pushq %5\n\t"             /* restore RIP */   \
   10.47 +                         "ret\n\t"                                      \
   10.48 +                         "1:\t"                                         \
   10.49 +                         "popq %%rbp\n\t"                               \
   10.50 +                         "popfq"                                        \
   10.51 +                         :"=m" (prev->sp),"=m" (prev->ip),            \
   10.52 +                          "=S" (rsi),"=D" (rdi)             \
   10.53 +                         :"m" (next->sp),"m" (next->ip),              \
   10.54 +                          "2" (prev), "d" (next));                      \
   10.55 +} while (0)
   10.56 +#endif
   10.57 +
   10.58 +
   10.59 +
   10.60 +          
   10.61 +#endif /* __ARCH_SCHED_H__ */
    11.1 --- a/extras/mini-os/include/x86/x86_32/hypercall-x86_32.h	Mon Nov 27 10:10:57 2006 -0700
    11.2 +++ b/extras/mini-os/include/x86/x86_32/hypercall-x86_32.h	Tue Nov 28 10:37:36 2006 -0700
    11.3 @@ -167,7 +167,7 @@ HYPERVISOR_fpu_taskswitch(
    11.4  
    11.5  static inline int
    11.6  HYPERVISOR_sched_op(
    11.7 -	int cmd, unsigned long arg)
    11.8 +	int cmd, void *arg)
    11.9  {
   11.10  	return _hypercall2(int, sched_op, cmd, arg);
   11.11  }
    12.1 --- a/extras/mini-os/include/x86/x86_64/hypercall-x86_64.h	Mon Nov 27 10:10:57 2006 -0700
    12.2 +++ b/extras/mini-os/include/x86/x86_64/hypercall-x86_64.h	Tue Nov 28 10:37:36 2006 -0700
    12.3 @@ -171,7 +171,7 @@ HYPERVISOR_fpu_taskswitch(
    12.4  
    12.5  static inline int
    12.6  HYPERVISOR_sched_op(
    12.7 -	int cmd, unsigned long arg)
    12.8 +	int cmd, void *arg)
    12.9  {
   12.10  	return _hypercall2(int, sched_op, cmd, arg);
   12.11  }
    13.1 --- a/extras/mini-os/kernel.c	Mon Nov 27 10:10:57 2006 -0700
    13.2 +++ b/extras/mini-os/kernel.c	Tue Nov 28 10:37:36 2006 -0700
    13.3 @@ -159,5 +159,9 @@ void start_kernel(start_info_t *si)
    13.4  void do_exit(void)
    13.5  {
    13.6      printk("Do_exit called!\n");
    13.7 -    for ( ;; ) HYPERVISOR_sched_op(SCHEDOP_shutdown, SHUTDOWN_crash);
    13.8 +    for( ;; )
    13.9 +    {
   13.10 +        struct sched_shutdown sched_shutdown = { .reason = SHUTDOWN_crash };
   13.11 +        HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown);
   13.12 +    }
   13.13  }
    14.1 --- a/extras/mini-os/mm.c	Mon Nov 27 10:10:57 2006 -0700
    14.2 +++ b/extras/mini-os/mm.c	Tue Nov 28 10:37:36 2006 -0700
    14.3 @@ -48,10 +48,6 @@
    14.4  #define DEBUG(_f, _a...)    ((void)0)
    14.5  #endif
    14.6  
    14.7 -unsigned long *phys_to_machine_mapping;
    14.8 -extern char *stack;
    14.9 -extern void page_walk(unsigned long virt_addr);
   14.10 -
   14.11  /*********************
   14.12   * ALLOCATION BITMAP
   14.13   *  One bit per page of memory. Bit set => page is allocated.
   14.14 @@ -226,11 +222,11 @@ static void init_page_allocator(unsigned
   14.15      /* All allocated by default. */
   14.16      memset(alloc_bitmap, ~0, bitmap_size);
   14.17      /* Free up the memory we've been given to play with. */
   14.18 -    map_free(min>>PAGE_SHIFT, range>>PAGE_SHIFT);
   14.19 +    map_free(PHYS_PFN(min), range>>PAGE_SHIFT);
   14.20  
   14.21      /* The buddy lists are addressed in high memory. */
   14.22 -    min += VIRT_START;
   14.23 -    max += VIRT_START;
   14.24 +    min = (unsigned long) to_virt(min);
   14.25 +    max = (unsigned long) to_virt(max);
   14.26  
   14.27      while ( range != 0 )
   14.28      {
   14.29 @@ -297,7 +293,7 @@ unsigned long alloc_pages(int order)
   14.30          free_head[i] = spare_ch;
   14.31      }
   14.32      
   14.33 -    map_alloc(to_phys(alloc_ch)>>PAGE_SHIFT, 1<<order);
   14.34 +    map_alloc(PHYS_PFN(to_phys(alloc_ch)), 1<<order);
   14.35  
   14.36      return((unsigned long)alloc_ch);
   14.37  
   14.38 @@ -365,350 +361,6 @@ void free_pages(void *pointer, int order
   14.39  }
   14.40  
   14.41  
   14.42 -void new_pt_frame(unsigned long *pt_pfn, unsigned long prev_l_mfn, 
   14.43 -                                unsigned long offset, unsigned long level)
   14.44 -{   
   14.45 -    pgentry_t *tab = (pgentry_t *)start_info.pt_base;
   14.46 -    unsigned long pt_page = (unsigned long)pfn_to_virt(*pt_pfn); 
   14.47 -    unsigned long prot_e, prot_t, pincmd;
   14.48 -    mmu_update_t mmu_updates[1];
   14.49 -    struct mmuext_op pin_request;
   14.50 -    
   14.51 -    DEBUG("Allocating new L%d pt frame for pt_pfn=%lx, "
   14.52 -           "prev_l_mfn=%lx, offset=%lx", 
   14.53 -           level, *pt_pfn, prev_l_mfn, offset);
   14.54 -
   14.55 -    /* We need to clear the page, otherwise we might fail to map it
   14.56 -       as a page table page */
   14.57 -    memset((unsigned long*)pfn_to_virt(*pt_pfn), 0, PAGE_SIZE);  
   14.58 - 
   14.59 -    switch ( level )
   14.60 -    {
   14.61 -    case L1_FRAME:
   14.62 -         prot_e = L1_PROT;
   14.63 -         prot_t = L2_PROT;
   14.64 -         pincmd = MMUEXT_PIN_L1_TABLE;
   14.65 -         break;
   14.66 -#if defined(__x86_64__) || defined(CONFIG_X86_PAE)
   14.67 -    case L2_FRAME:
   14.68 -         prot_e = L2_PROT;
   14.69 -         prot_t = L3_PROT;
   14.70 -         pincmd = MMUEXT_PIN_L2_TABLE;
   14.71 -         break;
   14.72 -#endif
   14.73 -#if defined(__x86_64__)
   14.74 -    case L3_FRAME:
   14.75 -         prot_e = L3_PROT;
   14.76 -         prot_t = L4_PROT;
   14.77 -         pincmd = MMUEXT_PIN_L3_TABLE;
   14.78 -         break;
   14.79 -#endif
   14.80 -    default:
   14.81 -         printk("new_pt_frame() called with invalid level number %d\n", level);
   14.82 -         do_exit();
   14.83 -         break;
   14.84 -    }
   14.85 -    /* Update the entry */
   14.86 -#if defined(__x86_64__)
   14.87 -    tab = pte_to_virt(tab[l4_table_offset(pt_page)]);
   14.88 -    tab = pte_to_virt(tab[l3_table_offset(pt_page)]);
   14.89 -#endif
   14.90 -#if defined(CONFIG_X86_PAE)
   14.91 -    tab = pte_to_virt(tab[l3_table_offset(pt_page)]);
   14.92 -#endif
   14.93 -
   14.94 -    mmu_updates[0].ptr = ((pgentry_t)tab[l2_table_offset(pt_page)] & PAGE_MASK) + 
   14.95 -                         sizeof(pgentry_t) * l1_table_offset(pt_page);
   14.96 -    mmu_updates[0].val = (pgentry_t)pfn_to_mfn(*pt_pfn) << PAGE_SHIFT | 
   14.97 -                         (prot_e & ~_PAGE_RW);
   14.98 -    if(HYPERVISOR_mmu_update(mmu_updates, 1, NULL, DOMID_SELF) < 0)
   14.99 -    {
  14.100 -         printk("PTE for new page table page could not be updated\n");
  14.101 -         do_exit();
  14.102 -    }
  14.103 -                        
  14.104 -    /* Pin the page to provide correct protection */
  14.105 -    pin_request.cmd = pincmd;
  14.106 -    pin_request.arg1.mfn = pfn_to_mfn(*pt_pfn);
  14.107 -    if(HYPERVISOR_mmuext_op(&pin_request, 1, NULL, DOMID_SELF) < 0)
  14.108 -    {
  14.109 -        printk("ERROR: pinning failed\n");
  14.110 -        do_exit();
  14.111 -    }
  14.112 -
  14.113 -    /* Now fill the new page table page with entries.
  14.114 -       Update the page directory as well. */
  14.115 -    mmu_updates[0].ptr = ((pgentry_t)prev_l_mfn << PAGE_SHIFT) + sizeof(pgentry_t) * offset;
  14.116 -    mmu_updates[0].val = (pgentry_t)pfn_to_mfn(*pt_pfn) << PAGE_SHIFT | prot_t;
  14.117 -    if(HYPERVISOR_mmu_update(mmu_updates, 1, NULL, DOMID_SELF) < 0) 
  14.118 -    {
  14.119 -       printk("ERROR: mmu_update failed\n");
  14.120 -       do_exit();
  14.121 -    }
  14.122 -    *pt_pfn += 1;
  14.123 -}
  14.124 -
  14.125 -/* Checks if a pagetable frame is needed (if weren't allocated by Xen) */
  14.126 -static int need_pt_frame(unsigned long virt_address, int level)
  14.127 -{
  14.128 -    unsigned long hyp_virt_start = HYPERVISOR_VIRT_START;
  14.129 -#if defined(__x86_64__)
  14.130 -    unsigned long hyp_virt_end = HYPERVISOR_VIRT_END;
  14.131 -#else
  14.132 -    unsigned long hyp_virt_end = 0xffffffff;
  14.133 -#endif
  14.134 -
  14.135 -    /* In general frames will _not_ be needed if they were already
  14.136 -       allocated to map the hypervisor into our VA space */
  14.137 -#if defined(__x86_64__)
  14.138 -    if(level == L3_FRAME)
  14.139 -    {
  14.140 -        if(l4_table_offset(virt_address) >= 
  14.141 -           l4_table_offset(hyp_virt_start) &&
  14.142 -           l4_table_offset(virt_address) <= 
  14.143 -           l4_table_offset(hyp_virt_end))
  14.144 -            return 0;
  14.145 -        return 1;
  14.146 -    } else
  14.147 -#endif
  14.148 -
  14.149 -#if defined(__x86_64__) || defined(CONFIG_X86_PAE)
  14.150 -    if(level == L2_FRAME)
  14.151 -    {
  14.152 -#if defined(__x86_64__)
  14.153 -        if(l4_table_offset(virt_address) >= 
  14.154 -           l4_table_offset(hyp_virt_start) &&
  14.155 -           l4_table_offset(virt_address) <= 
  14.156 -           l4_table_offset(hyp_virt_end))
  14.157 -#endif
  14.158 -            if(l3_table_offset(virt_address) >= 
  14.159 -               l3_table_offset(hyp_virt_start) &&
  14.160 -               l3_table_offset(virt_address) <= 
  14.161 -               l3_table_offset(hyp_virt_end))
  14.162 -                return 0;
  14.163 -
  14.164 -        return 1;
  14.165 -    } else 
  14.166 -#endif /* defined(__x86_64__) || defined(CONFIG_X86_PAE) */
  14.167 -
  14.168 -    /* Always need l1 frames */
  14.169 -    if(level == L1_FRAME)
  14.170 -        return 1;
  14.171 -
  14.172 -    printk("ERROR: Unknown frame level %d, hypervisor %llx,%llx\n", 
  14.173 -        level, hyp_virt_start, hyp_virt_end);
  14.174 -    return -1;
  14.175 -}
  14.176 -
  14.177 -void build_pagetable(unsigned long *start_pfn, unsigned long *max_pfn)
  14.178 -{
  14.179 -    unsigned long start_address, end_address;
  14.180 -    unsigned long pfn_to_map, pt_pfn = *start_pfn;
  14.181 -    static mmu_update_t mmu_updates[L1_PAGETABLE_ENTRIES + 1];
  14.182 -    pgentry_t *tab = (pgentry_t *)start_info.pt_base, page;
  14.183 -    unsigned long mfn = pfn_to_mfn(virt_to_pfn(start_info.pt_base));
  14.184 -    unsigned long offset;
  14.185 -    int count = 0;
  14.186 -
  14.187 -    pfn_to_map = (start_info.nr_pt_frames - NOT_L1_FRAMES) * L1_PAGETABLE_ENTRIES;
  14.188 -
  14.189 -    if (*max_pfn >= virt_to_pfn(HYPERVISOR_VIRT_START))
  14.190 -    {
  14.191 -        printk("WARNING: Mini-OS trying to use Xen virtual space. "
  14.192 -               "Truncating memory from %dMB to ",
  14.193 -               ((unsigned long)pfn_to_virt(*max_pfn) - (unsigned long)&_text)>>20);
  14.194 -        *max_pfn = virt_to_pfn(HYPERVISOR_VIRT_START - PAGE_SIZE);
  14.195 -        printk("%dMB\n",
  14.196 -               ((unsigned long)pfn_to_virt(*max_pfn) - (unsigned long)&_text)>>20);
  14.197 -    }
  14.198 -
  14.199 -    start_address = (unsigned long)pfn_to_virt(pfn_to_map);
  14.200 -    end_address = (unsigned long)pfn_to_virt(*max_pfn);
  14.201 -
  14.202 -    /* We worked out the virtual memory range to map, now mapping loop */
  14.203 -    printk("Mapping memory range 0x%lx - 0x%lx\n", start_address, end_address);
  14.204 -
  14.205 -    while(start_address < end_address)
  14.206 -    {
  14.207 -        tab = (pgentry_t *)start_info.pt_base;
  14.208 -        mfn = pfn_to_mfn(virt_to_pfn(start_info.pt_base));
  14.209 -
  14.210 -#if defined(__x86_64__)
  14.211 -        offset = l4_table_offset(start_address);
  14.212 -        /* Need new L3 pt frame */
  14.213 -        if(!(start_address & L3_MASK)) 
  14.214 -            if(need_pt_frame(start_address, L3_FRAME)) 
  14.215 -                new_pt_frame(&pt_pfn, mfn, offset, L3_FRAME);
  14.216 -
  14.217 -        page = tab[offset];
  14.218 -        mfn = pte_to_mfn(page);
  14.219 -        tab = to_virt(mfn_to_pfn(mfn) << PAGE_SHIFT);
  14.220 -#endif
  14.221 -#if defined(__x86_64__) || defined(CONFIG_X86_PAE)
  14.222 -        offset = l3_table_offset(start_address);
  14.223 -        /* Need new L2 pt frame */
  14.224 -        if(!(start_address & L2_MASK))
  14.225 -            if(need_pt_frame(start_address, L2_FRAME))
  14.226 -                new_pt_frame(&pt_pfn, mfn, offset, L2_FRAME);
  14.227 -
  14.228 -        page = tab[offset];
  14.229 -        mfn = pte_to_mfn(page);
  14.230 -        tab = to_virt(mfn_to_pfn(mfn) << PAGE_SHIFT);
  14.231 -#endif
  14.232 -        offset = l2_table_offset(start_address);        
  14.233 -        /* Need new L1 pt frame */
  14.234 -        if(!(start_address & L1_MASK))
  14.235 -            if(need_pt_frame(start_address, L1_FRAME)) 
  14.236 -                new_pt_frame(&pt_pfn, mfn, offset, L1_FRAME);
  14.237 -
  14.238 -        page = tab[offset];
  14.239 -        mfn = pte_to_mfn(page);
  14.240 -        offset = l1_table_offset(start_address);
  14.241 -
  14.242 -        mmu_updates[count].ptr = ((pgentry_t)mfn << PAGE_SHIFT) + sizeof(pgentry_t) * offset;
  14.243 -        mmu_updates[count].val = (pgentry_t)pfn_to_mfn(pfn_to_map++) << PAGE_SHIFT | L1_PROT;
  14.244 -        count++;
  14.245 -        if (count == L1_PAGETABLE_ENTRIES || pfn_to_map == *max_pfn)
  14.246 -        {
  14.247 -            if(HYPERVISOR_mmu_update(mmu_updates, count, NULL, DOMID_SELF) < 0)
  14.248 -            {
  14.249 -                printk("PTE could not be updated\n");
  14.250 -                do_exit();
  14.251 -            }
  14.252 -            count = 0;
  14.253 -        }
  14.254 -        start_address += PAGE_SIZE;
  14.255 -    }
  14.256 -    *start_pfn = pt_pfn;
  14.257 -}
  14.258 -
  14.259 -
  14.260 -void mem_test(unsigned long *start_add, unsigned long *end_add)
  14.261 -{
  14.262 -    unsigned long mask = 0x10000;
  14.263 -    unsigned long *pointer;
  14.264 -
  14.265 -    for(pointer = start_add; pointer < end_add; pointer++)
  14.266 -    {
  14.267 -        if(!(((unsigned long)pointer) & 0xfffff))
  14.268 -        {
  14.269 -            printk("Writing to %lx\n", pointer);
  14.270 -            page_walk((unsigned long)pointer);
  14.271 -        }
  14.272 -        *pointer = (unsigned long)pointer & ~mask;
  14.273 -    }
  14.274 -
  14.275 -    for(pointer = start_add; pointer < end_add; pointer++)
  14.276 -    {
  14.277 -        if(((unsigned long)pointer & ~mask) != *pointer)
  14.278 -            printk("Read error at 0x%lx. Read: 0x%lx, should read 0x%lx\n",
  14.279 -                (unsigned long)pointer, 
  14.280 -                *pointer, 
  14.281 -                ((unsigned long)pointer & ~mask));
  14.282 -    }
  14.283 -
  14.284 -}
  14.285 -
  14.286 -static pgentry_t *demand_map_pgt;
  14.287 -static void *demand_map_area_start;
  14.288 -
  14.289 -static void init_demand_mapping_area(unsigned long max_pfn)
  14.290 -{
  14.291 -    unsigned long mfn;
  14.292 -    pgentry_t *tab;
  14.293 -    unsigned long start_addr;
  14.294 -    unsigned long pt_pfn;
  14.295 -    unsigned offset;
  14.296 -
  14.297 -    /* Round up to four megs.  + 1024 rather than + 1023 since we want
  14.298 -       to be sure we don't end up in the same place we started. */
  14.299 -    max_pfn = (max_pfn + L1_PAGETABLE_ENTRIES) & ~(L1_PAGETABLE_ENTRIES - 1);
  14.300 -    if (max_pfn == 0 ||
  14.301 -            (unsigned long)pfn_to_virt(max_pfn + L1_PAGETABLE_ENTRIES) >=
  14.302 -            HYPERVISOR_VIRT_START) {
  14.303 -        printk("Too much memory; no room for demand map hole.\n");
  14.304 -        do_exit();
  14.305 -    }
  14.306 -
  14.307 -    demand_map_area_start = pfn_to_virt(max_pfn);
  14.308 -    printk("Demand map pfns start at %lx (%p).\n", max_pfn,
  14.309 -            demand_map_area_start);
  14.310 -    start_addr = (unsigned long)demand_map_area_start;
  14.311 -
  14.312 -    tab = (pgentry_t *)start_info.pt_base;
  14.313 -    mfn = virt_to_mfn(start_info.pt_base);
  14.314 -    pt_pfn = virt_to_pfn(alloc_page());
  14.315 -
  14.316 -#if defined(__x86_64__)
  14.317 -    offset = l4_table_offset(start_addr);
  14.318 -    if (!(tab[offset] & _PAGE_PRESENT)) {
  14.319 -        new_pt_frame(&pt_pfn, mfn, offset, L3_FRAME);
  14.320 -        pt_pfn = virt_to_pfn(alloc_page());
  14.321 -    }
  14.322 -    ASSERT(tab[offset] & _PAGE_PRESENT);
  14.323 -    mfn = pte_to_mfn(tab[offset]);
  14.324 -    tab = to_virt(mfn_to_pfn(mfn) << PAGE_SHIFT);
  14.325 -#endif
  14.326 -#if defined(__x86_64__) || defined(CONFIG_X86_PAE)
  14.327 -    offset = l3_table_offset(start_addr);
  14.328 -    if (!(tab[offset] & _PAGE_PRESENT)) {
  14.329 -        new_pt_frame(&pt_pfn, mfn, offset, L2_FRAME);
  14.330 -        pt_pfn = virt_to_pfn(alloc_page());
  14.331 -    }
  14.332 -    ASSERT(tab[offset] & _PAGE_PRESENT);
  14.333 -    mfn = pte_to_mfn(tab[offset]);
  14.334 -    tab = to_virt(mfn_to_pfn(mfn) << PAGE_SHIFT);
  14.335 -#endif
  14.336 -    offset = l2_table_offset(start_addr);
  14.337 -    if (tab[offset] & _PAGE_PRESENT) {
  14.338 -        printk("Demand map area already has a page table covering it?\n");
  14.339 -        BUG();
  14.340 -    }
  14.341 -    demand_map_pgt = pfn_to_virt(pt_pfn);
  14.342 -    new_pt_frame(&pt_pfn, mfn, offset, L1_FRAME);
  14.343 -    ASSERT(tab[offset] & _PAGE_PRESENT);
  14.344 -}
  14.345 -
  14.346 -void *map_frames(unsigned long *f, unsigned long n)
  14.347 -{
  14.348 -    unsigned long x;
  14.349 -    unsigned long y = 0;
  14.350 -    mmu_update_t mmu_updates[16];
  14.351 -    int rc;
  14.352 -
  14.353 -    if (n > 16) {
  14.354 -        printk("Tried to map too many (%ld) frames at once.\n", n);
  14.355 -        return NULL;
  14.356 -    }
  14.357 -
  14.358 -    /* Find a run of n contiguous frames */
  14.359 -    for (x = 0; x <= 1024 - n; x += y + 1) {
  14.360 -        for (y = 0; y < n; y++)
  14.361 -            if (demand_map_pgt[x+y] & _PAGE_PRESENT)
  14.362 -                break;
  14.363 -        if (y == n)
  14.364 -            break;
  14.365 -    }
  14.366 -    if (y != n) {
  14.367 -        printk("Failed to map %ld frames!\n", n);
  14.368 -        return NULL;
  14.369 -    }
  14.370 -
  14.371 -    /* Found it at x.  Map it in. */
  14.372 -    for (y = 0; y < n; y++) {
  14.373 -        mmu_updates[y].ptr = virt_to_mach(&demand_map_pgt[x + y]);
  14.374 -        mmu_updates[y].val = (f[y] << PAGE_SHIFT) | L1_PROT;
  14.375 -    }
  14.376 -
  14.377 -    rc = HYPERVISOR_mmu_update(mmu_updates, n, NULL, DOMID_SELF);
  14.378 -    if (rc < 0) {
  14.379 -        printk("Map %ld failed: %d.\n", n, rc);
  14.380 -        return NULL;
  14.381 -    } else {
  14.382 -        return (void *)(unsigned long)((unsigned long)demand_map_area_start +
  14.383 -                x * PAGE_SIZE);
  14.384 -    }
  14.385 -}
  14.386  
  14.387  void init_mm(void)
  14.388  {
  14.389 @@ -717,22 +369,7 @@ void init_mm(void)
  14.390  
  14.391      printk("MM: Init\n");
  14.392  
  14.393 -    printk("  _text:        %p\n", &_text);
  14.394 -    printk("  _etext:       %p\n", &_etext);
  14.395 -    printk("  _edata:       %p\n", &_edata);
  14.396 -    printk("  stack start:  %p\n", &stack);
  14.397 -    printk("  _end:         %p\n", &_end);
  14.398 -
  14.399 -    /* First page follows page table pages and 3 more pages (store page etc) */
  14.400 -    start_pfn = PFN_UP(to_phys(start_info.pt_base)) + 
  14.401 -                start_info.nr_pt_frames + 3;
  14.402 -    max_pfn = start_info.nr_pages;
  14.403 -   
  14.404 -    printk("  start_pfn:    %lx\n", start_pfn);
  14.405 -    printk("  max_pfn:      %lx\n", max_pfn);
  14.406 -
  14.407 -    build_pagetable(&start_pfn, &max_pfn);
  14.408 -
  14.409 +    arch_init_mm(&start_pfn, &max_pfn);
  14.410      /*
  14.411       * now we can initialise the page allocator
  14.412       */
  14.413 @@ -742,8 +379,7 @@ void init_mm(void)
  14.414      init_page_allocator(PFN_PHYS(start_pfn), PFN_PHYS(max_pfn));
  14.415      printk("MM: done\n");
  14.416  
  14.417 -    init_demand_mapping_area(max_pfn);
  14.418 -    printk("Initialised demand area.\n");
  14.419 +    arch_init_demand_mapping_area(max_pfn);
  14.420  }
  14.421  
  14.422  void sanity_check(void)
    15.1 --- a/extras/mini-os/sched.c	Mon Nov 27 10:10:57 2006 -0700
    15.2 +++ b/extras/mini-os/sched.c	Tue Nov 28 10:37:36 2006 -0700
    15.3 @@ -54,82 +54,9 @@
    15.4  #define DEBUG(_f, _a...)    ((void)0)
    15.5  #endif
    15.6  
    15.7 -
    15.8 -#define RUNNABLE_FLAG   0x00000001
    15.9 -
   15.10 -#define is_runnable(_thread)    (_thread->flags & RUNNABLE_FLAG)
   15.11 -#define set_runnable(_thread)   (_thread->flags |= RUNNABLE_FLAG)
   15.12 -#define clear_runnable(_thread) (_thread->flags &= ~RUNNABLE_FLAG)
   15.13 -
   15.14 -
   15.15  struct thread *idle_thread = NULL;
   15.16  LIST_HEAD(exited_threads);
   15.17  
   15.18 -void idle_thread_fn(void *unused);
   15.19 -
   15.20 -void dump_stack(struct thread *thread)
   15.21 -{
   15.22 -    unsigned long *bottom = (unsigned long *)(thread->stack + 2*4*1024); 
   15.23 -    unsigned long *pointer = (unsigned long *)thread->sp;
   15.24 -    int count;
   15.25 -    if(thread == current)
   15.26 -    {
   15.27 -#ifdef __i386__    
   15.28 -        asm("movl %%esp,%0"
   15.29 -            : "=r"(pointer));
   15.30 -#else
   15.31 -        asm("movq %%rsp,%0"
   15.32 -            : "=r"(pointer));
   15.33 -#endif
   15.34 -    }
   15.35 -    printk("The stack for \"%s\"\n", thread->name);
   15.36 -    for(count = 0; count < 25 && pointer < bottom; count ++)
   15.37 -    {
   15.38 -        printk("[0x%lx] 0x%lx\n", pointer, *pointer);
   15.39 -        pointer++;
   15.40 -    }
   15.41 -    
   15.42 -    if(pointer < bottom) printk(" ... continues.\n");
   15.43 -}
   15.44 -
   15.45 -#ifdef __i386__
   15.46 -#define switch_threads(prev, next) do {                                 \
   15.47 -    unsigned long esi,edi;                                              \
   15.48 -    __asm__ __volatile__("pushfl\n\t"                                   \
   15.49 -                         "pushl %%ebp\n\t"                              \
   15.50 -                         "movl %%esp,%0\n\t"         /* save ESP */     \
   15.51 -                         "movl %4,%%esp\n\t"        /* restore ESP */   \
   15.52 -                         "movl $1f,%1\n\t"          /* save EIP */      \
   15.53 -                         "pushl %5\n\t"             /* restore EIP */   \
   15.54 -                         "ret\n\t"                                      \
   15.55 -                         "1:\t"                                         \
   15.56 -                         "popl %%ebp\n\t"                               \
   15.57 -                         "popfl"                                        \
   15.58 -                         :"=m" (prev->sp),"=m" (prev->ip),            \
   15.59 -                          "=S" (esi),"=D" (edi)             \
   15.60 -                         :"m" (next->sp),"m" (next->ip),              \
   15.61 -                          "2" (prev), "d" (next));                      \
   15.62 -} while (0)
   15.63 -#elif __x86_64__
   15.64 -#define switch_threads(prev, next) do {                                 \
   15.65 -    unsigned long rsi,rdi;                                              \
   15.66 -    __asm__ __volatile__("pushfq\n\t"                                   \
   15.67 -                         "pushq %%rbp\n\t"                              \
   15.68 -                         "movq %%rsp,%0\n\t"         /* save RSP */     \
   15.69 -                         "movq %4,%%rsp\n\t"        /* restore RSP */   \
   15.70 -                         "movq $1f,%1\n\t"          /* save RIP */      \
   15.71 -                         "pushq %5\n\t"             /* restore RIP */   \
   15.72 -                         "ret\n\t"                                      \
   15.73 -                         "1:\t"                                         \
   15.74 -                         "popq %%rbp\n\t"                               \
   15.75 -                         "popfq"                                        \
   15.76 -                         :"=m" (prev->sp),"=m" (prev->ip),            \
   15.77 -                          "=S" (rsi),"=D" (rdi)             \
   15.78 -                         :"m" (next->sp),"m" (next->ip),              \
   15.79 -                          "2" (prev), "d" (next));                      \
   15.80 -} while (0)
   15.81 -#endif
   15.82 -
   15.83  void inline print_runqueue(void)
   15.84  {
   15.85      struct list_head *it;
   15.86 @@ -250,50 +177,6 @@ void exit_thread(void)
   15.87      schedule();
   15.88  }
   15.89  
   15.90 -/* Pushes the specified value onto the stack of the specified thread */
   15.91 -static void stack_push(struct thread *thread, unsigned long value)
   15.92 -{
   15.93 -    thread->sp -= sizeof(unsigned long);
   15.94 -    *((unsigned long *)thread->sp) = value;
   15.95 -}
   15.96 -
   15.97 -struct thread* create_thread(char *name, void (*function)(void *), void *data)
   15.98 -{
   15.99 -    struct thread *thread;
  15.100 -    unsigned long flags;
  15.101 -    
  15.102 -    thread = xmalloc(struct thread);
  15.103 -    /* Allocate 2 pages for stack, stack will be 2pages aligned */
  15.104 -    thread->stack = (char *)alloc_pages(1);
  15.105 -    thread->name = name;
  15.106 -    printk("Thread \"%s\": pointer: 0x%lx, stack: 0x%lx\n", name, thread, 
  15.107 -            thread->stack);
  15.108 -    
  15.109 -    thread->sp = (unsigned long)thread->stack + 4096 * 2;
  15.110 -    /* Save pointer to the thread on the stack, used by current macro */
  15.111 -    *((unsigned long *)thread->stack) = (unsigned long)thread;
  15.112 -    
  15.113 -    stack_push(thread, (unsigned long) function);
  15.114 -    stack_push(thread, (unsigned long) data);
  15.115 -    thread->ip = (unsigned long) thread_starter;
  15.116 -     
  15.117 -    /* Not runable, not exited, not sleeping */
  15.118 -    thread->flags = 0;
  15.119 -    thread->wakeup_time = 0LL;
  15.120 -    set_runnable(thread);
  15.121 -    local_irq_save(flags);
  15.122 -    if(idle_thread != NULL) {
  15.123 -        list_add_tail(&thread->thread_list, &idle_thread->thread_list); 
  15.124 -    } else if(function != idle_thread_fn)
  15.125 -    {
  15.126 -        printk("BUG: Not allowed to create thread before initialising scheduler.\n");
  15.127 -        BUG();
  15.128 -    }
  15.129 -    local_irq_restore(flags);
  15.130 -    return thread;
  15.131 -}
  15.132 -
  15.133 -
  15.134  void block(struct thread *thread)
  15.135  {
  15.136      thread->wakeup_time = 0LL;
  15.137 @@ -327,26 +210,6 @@ void idle_thread_fn(void *unused)
  15.138      }
  15.139  }
  15.140  
  15.141 -void run_idle_thread(void)
  15.142 -{
  15.143 -    /* Switch stacks and run the thread */ 
  15.144 -#if defined(__i386__)
  15.145 -    __asm__ __volatile__("mov %0,%%esp\n\t"
  15.146 -                         "push %1\n\t" 
  15.147 -                         "ret"                                            
  15.148 -                         :"=m" (idle_thread->sp)
  15.149 -                         :"m" (idle_thread->ip));                          
  15.150 -#elif defined(__x86_64__)
  15.151 -    __asm__ __volatile__("mov %0,%%rsp\n\t"
  15.152 -                         "push %1\n\t" 
  15.153 -                         "ret"                                            
  15.154 -                         :"=m" (idle_thread->sp)
  15.155 -                         :"m" (idle_thread->ip));                                                    
  15.156 -#endif
  15.157 -}
  15.158 -
  15.159 -
  15.160 -
  15.161  DECLARE_MUTEX(mutex);
  15.162  
  15.163  void th_f1(void *data)
    16.1 --- a/linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c	Mon Nov 27 10:10:57 2006 -0700
    16.2 +++ b/linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c	Tue Nov 28 10:37:36 2006 -0700
    16.3 @@ -99,18 +99,6 @@ void xen_l4_entry_update(pgd_t *ptr, pgd
    16.4  }
    16.5  #endif /* CONFIG_X86_64 */
    16.6  
    16.7 -void xen_machphys_update(unsigned long mfn, unsigned long pfn)
    16.8 -{
    16.9 -	mmu_update_t u;
   16.10 -	if (xen_feature(XENFEAT_auto_translated_physmap)) {
   16.11 -		BUG_ON(pfn != mfn);
   16.12 -		return;
   16.13 -	}
   16.14 -	u.ptr = ((unsigned long long)mfn << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE;
   16.15 -	u.val = pfn;
   16.16 -	BUG_ON(HYPERVISOR_mmu_update(&u, 1, NULL, DOMID_SELF) < 0);
   16.17 -}
   16.18 -
   16.19  void xen_pt_switch(unsigned long ptr)
   16.20  {
   16.21  	struct mmuext_op op;
    17.1 --- a/linux-2.6-xen-sparse/arch/i386/oprofile/Makefile	Mon Nov 27 10:10:57 2006 -0700
    17.2 +++ b/linux-2.6-xen-sparse/arch/i386/oprofile/Makefile	Tue Nov 28 10:37:36 2006 -0700
    17.3 @@ -7,7 +7,10 @@ DRIVER_OBJS = $(addprefix ../../../drive
    17.4  		timer_int.o )
    17.5  
    17.6  ifdef CONFIG_XEN
    17.7 -oprofile-y				:= $(DRIVER_OBJS) xenoprof.o
    17.8 +XENOPROF_COMMON_OBJS = $(addprefix ../../../drivers/xen/xenoprof/, \
    17.9 +			 xenoprofile.o)
   17.10 +oprofile-y				:= $(DRIVER_OBJS) \
   17.11 +					   $(XENOPROF_COMMON_OBJS) xenoprof.o
   17.12  else 
   17.13  oprofile-y				:= $(DRIVER_OBJS) init.o backtrace.o
   17.14  oprofile-$(CONFIG_X86_LOCAL_APIC) 	+= nmi_int.o op_model_athlon.o \
    18.1 --- a/linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c	Mon Nov 27 10:10:57 2006 -0700
    18.2 +++ b/linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c	Tue Nov 28 10:37:36 2006 -0700
    18.3 @@ -9,249 +9,83 @@
    18.4   * Modified by Aravind Menon and Jose Renato Santos for Xen
    18.5   * These modifications are:
    18.6   * Copyright (C) 2005 Hewlett-Packard Co.
    18.7 + *
    18.8 + * x86-specific part
    18.9 + * Copyright (c) 2006 Isaku Yamahata <yamahata at valinux co jp>
   18.10 + *                    VA Linux Systems Japan K.K.
   18.11   */
   18.12  
   18.13  #include <linux/init.h>
   18.14 -#include <linux/notifier.h>
   18.15 -#include <linux/smp.h>
   18.16  #include <linux/oprofile.h>
   18.17 -#include <linux/sysdev.h>
   18.18 -#include <linux/slab.h>
   18.19 -#include <linux/interrupt.h>
   18.20 -#include <linux/vmalloc.h>
   18.21 -#include <asm/nmi.h>
   18.22 -#include <asm/msr.h>
   18.23 -#include <asm/apic.h>
   18.24 +#include <linux/sched.h>
   18.25  #include <asm/pgtable.h>
   18.26 -#include <xen/evtchn.h>
   18.27 -#include "op_counter.h"
   18.28  
   18.29  #include <xen/driver_util.h>
   18.30  #include <xen/interface/xen.h>
   18.31  #include <xen/interface/xenoprof.h>
   18.32 -#include <../../../drivers/oprofile/cpu_buffer.h>
   18.33 -#include <../../../drivers/oprofile/event_buffer.h>
   18.34 -
   18.35 -#define MAX_XENOPROF_SAMPLES 16
   18.36 -
   18.37 -static int xenoprof_start(void);
   18.38 -static void xenoprof_stop(void);
   18.39 -
   18.40 -static int xenoprof_enabled = 0;
   18.41 -static unsigned int num_events = 0;
   18.42 -static int is_primary = 0;
   18.43 -static int active_defined;
   18.44 -
   18.45 -/* sample buffers shared with Xen */
   18.46 -xenoprof_buf_t * xenoprof_buf[MAX_VIRT_CPUS];
   18.47 -/* Shared buffer area */
   18.48 -char * shared_buffer = NULL;
   18.49 -/* Number of buffers in shared area (one per VCPU) */
   18.50 -int nbuf;
   18.51 -/* Mappings of VIRQ_XENOPROF to irq number (per cpu) */
   18.52 -int ovf_irq[NR_CPUS];
   18.53 -/* cpu model type string - copied from Xen memory space on XENOPROF_init command */
   18.54 -char cpu_type[XENOPROF_CPU_TYPE_SIZE];
   18.55 -
   18.56 -/* Passive sample buffers shared with Xen */
   18.57 -xenoprof_buf_t *p_xenoprof_buf[MAX_OPROF_DOMAINS][MAX_VIRT_CPUS];
   18.58 -/* Passive shared buffer area */
   18.59 -char *p_shared_buffer[MAX_OPROF_DOMAINS];
   18.60 -
   18.61 -#ifdef CONFIG_PM
   18.62 -
   18.63 -static int xenoprof_suspend(struct sys_device * dev, pm_message_t state)
   18.64 -{
   18.65 -	if (xenoprof_enabled == 1)
   18.66 -		xenoprof_stop();
   18.67 -	return 0;
   18.68 -}
   18.69 -
   18.70 +#include <xen/xenoprof.h>
   18.71 +#include "op_counter.h"
   18.72  
   18.73 -static int xenoprof_resume(struct sys_device * dev)
   18.74 -{
   18.75 -	if (xenoprof_enabled == 1)
   18.76 -		xenoprof_start();
   18.77 -	return 0;
   18.78 -}
   18.79 -
   18.80 -
   18.81 -static struct sysdev_class oprofile_sysclass = {
   18.82 -	set_kset_name("oprofile"),
   18.83 -	.resume		= xenoprof_resume,
   18.84 -	.suspend	= xenoprof_suspend
   18.85 -};
   18.86 -
   18.87 -
   18.88 -static struct sys_device device_oprofile = {
   18.89 -	.id	= 0,
   18.90 -	.cls	= &oprofile_sysclass,
   18.91 -};
   18.92 -
   18.93 +static unsigned int num_events = 0;
   18.94  
   18.95 -static int __init init_driverfs(void)
   18.96 -{
   18.97 -	int error;
   18.98 -	if (!(error = sysdev_class_register(&oprofile_sysclass)))
   18.99 -		error = sysdev_register(&device_oprofile);
  18.100 -	return error;
  18.101 -}
  18.102 -
  18.103 -
  18.104 -static void __exit exit_driverfs(void)
  18.105 -{
  18.106 -	sysdev_unregister(&device_oprofile);
  18.107 -	sysdev_class_unregister(&oprofile_sysclass);
  18.108 -}
  18.109 -
  18.110 -#else
  18.111 -#define init_driverfs() do { } while (0)
  18.112 -#define exit_driverfs() do { } while (0)
  18.113 -#endif /* CONFIG_PM */
  18.114 -
  18.115 -unsigned long long oprofile_samples = 0;
  18.116 -unsigned long long p_oprofile_samples = 0;
  18.117 -
  18.118 -unsigned int pdomains;
  18.119 -struct xenoprof_passive passive_domains[MAX_OPROF_DOMAINS];
  18.120 -
  18.121 -static void xenoprof_add_pc(xenoprof_buf_t *buf, int is_passive)
  18.122 +void __init xenoprof_arch_init_counter(struct xenoprof_init *init)
  18.123  {
  18.124 -	int head, tail, size;
  18.125 -
  18.126 -	head = buf->event_head;
  18.127 -	tail = buf->event_tail;
  18.128 -	size = buf->event_size;
  18.129 -
  18.130 -	if (tail > head) {
  18.131 -		while (tail < size) {
  18.132 -			oprofile_add_pc(buf->event_log[tail].eip,
  18.133 -					buf->event_log[tail].mode,
  18.134 -					buf->event_log[tail].event);
  18.135 -			if (!is_passive)
  18.136 -				oprofile_samples++;
  18.137 -			else
  18.138 -				p_oprofile_samples++;
  18.139 -			tail++;
  18.140 -		}
  18.141 -		tail = 0;
  18.142 -	}
  18.143 -	while (tail < head) {
  18.144 -		oprofile_add_pc(buf->event_log[tail].eip,
  18.145 -				buf->event_log[tail].mode,
  18.146 -				buf->event_log[tail].event);
  18.147 -		if (!is_passive)
  18.148 -			oprofile_samples++;
  18.149 -		else
  18.150 -			p_oprofile_samples++;
  18.151 -		tail++;
  18.152 -	}
  18.153 -
  18.154 -	buf->event_tail = tail;
  18.155 -}
  18.156 -
  18.157 -static void xenoprof_handle_passive(void)
  18.158 -{
  18.159 -	int i, j;
  18.160 -	int flag_domain, flag_switch = 0;
  18.161 -	
  18.162 -	for (i = 0; i < pdomains; i++) {
  18.163 -		flag_domain = 0;
  18.164 -		for (j = 0; j < passive_domains[i].nbuf; j++) {
  18.165 -			xenoprof_buf_t *buf = p_xenoprof_buf[i][j];
  18.166 -			if (buf->event_head == buf->event_tail)
  18.167 -				continue;
  18.168 -			if (!flag_domain) {
  18.169 -				if (!oprofile_add_domain_switch(passive_domains[i].
  18.170 -								domain_id))
  18.171 -					goto done;
  18.172 -				flag_domain = 1;
  18.173 -			}
  18.174 -			xenoprof_add_pc(buf, 1);
  18.175 -			flag_switch = 1;
  18.176 -		}
  18.177 -	}
  18.178 -done:
  18.179 -	if (flag_switch)
  18.180 -		oprofile_add_domain_switch(COORDINATOR_DOMAIN);
  18.181 -}
  18.182 -
  18.183 -static irqreturn_t 
  18.184 -xenoprof_ovf_interrupt(int irq, void * dev_id, struct pt_regs * regs)
  18.185 -{
  18.186 -	struct xenoprof_buf * buf;
  18.187 -	int cpu;
  18.188 -	static unsigned long flag;
  18.189 -
  18.190 -	cpu = smp_processor_id();
  18.191 -	buf = xenoprof_buf[cpu];
  18.192 -
  18.193 -	xenoprof_add_pc(buf, 0);
  18.194 -
  18.195 -	if (is_primary && !test_and_set_bit(0, &flag)) {
  18.196 -		xenoprof_handle_passive();
  18.197 -		smp_mb__before_clear_bit();
  18.198 -		clear_bit(0, &flag);
  18.199 -	}
  18.200 -
  18.201 -	return IRQ_HANDLED;
  18.202 -}
  18.203 -
  18.204 -
  18.205 -static void unbind_virq(void)
  18.206 -{
  18.207 -	int i;
  18.208 -
  18.209 -	for_each_cpu(i) {
  18.210 -		if (ovf_irq[i] >= 0) {
  18.211 -			unbind_from_irqhandler(ovf_irq[i], NULL);
  18.212 -			ovf_irq[i] = -1;
  18.213 -		}
  18.214 +	num_events = init->num_events;
  18.215 +	/* just in case - make sure we do not overflow event list 
  18.216 +	   (i.e. counter_config list) */
  18.217 +	if (num_events > OP_MAX_COUNTER) {
  18.218 +		num_events = OP_MAX_COUNTER;
  18.219 +		init->num_events = num_events;
  18.220  	}
  18.221  }
  18.222  
  18.223 -
  18.224 -static int bind_virq(void)
  18.225 +void xenoprof_arch_counter(void)
  18.226  {
  18.227 -	int i, result;
  18.228 +	int i;
  18.229 +	struct xenoprof_counter counter;
  18.230  
  18.231 -	for_each_cpu(i) {
  18.232 -		result = bind_virq_to_irqhandler(VIRQ_XENOPROF,
  18.233 -						 i,
  18.234 -						 xenoprof_ovf_interrupt,
  18.235 -						 SA_INTERRUPT,
  18.236 -						 "xenoprof",
  18.237 -						 NULL);
  18.238 -
  18.239 -		if (result < 0) {
  18.240 -			unbind_virq();
  18.241 -			return result;
  18.242 -		}
  18.243 -
  18.244 -		ovf_irq[i] = result;
  18.245 +	for (i=0; i<num_events; i++) {
  18.246 +		counter.ind       = i;
  18.247 +		counter.count     = (uint64_t)counter_config[i].count;
  18.248 +		counter.enabled   = (uint32_t)counter_config[i].enabled;
  18.249 +		counter.event     = (uint32_t)counter_config[i].event;
  18.250 +		counter.kernel    = (uint32_t)counter_config[i].kernel;
  18.251 +		counter.user      = (uint32_t)counter_config[i].user;
  18.252 +		counter.unit_mask = (uint64_t)counter_config[i].unit_mask;
  18.253 +		HYPERVISOR_xenoprof_op(XENOPROF_counter, 
  18.254 +				       &counter);
  18.255  	}
  18.256 -		
  18.257 -	return 0;
  18.258  }
  18.259  
  18.260 -
  18.261 -static int map_xenoprof_buffer(int max_samples)
  18.262 +void xenoprof_arch_start(void) 
  18.263  {
  18.264 -	struct xenoprof_get_buffer get_buffer;
  18.265 -	struct xenoprof_buf *buf;
  18.266 -	int npages, ret, i;
  18.267 +	/* nothing */
  18.268 +}
  18.269 +
  18.270 +void xenoprof_arch_stop(void)
  18.271 +{
  18.272 +	/* nothing */
  18.273 +}
  18.274 +
  18.275 +void xenoprof_arch_unmap_shared_buffer(struct xenoprof_shared_buffer * sbuf)
  18.276 +{
  18.277 +	if (sbuf->buffer) {
  18.278 +		vunmap(sbuf->buffer);
  18.279 +		sbuf->buffer = NULL;
  18.280 +	}
  18.281 +}
  18.282 +
  18.283 +int xenoprof_arch_map_shared_buffer(struct xenoprof_get_buffer * get_buffer,
  18.284 +				    struct xenoprof_shared_buffer * sbuf)
  18.285 +{
  18.286 +	int npages, ret;
  18.287  	struct vm_struct *area;
  18.288  
  18.289 -	if ( shared_buffer )
  18.290 -		return 0;
  18.291 -
  18.292 -	get_buffer.max_samples = max_samples;
  18.293 -
  18.294 -	if ( (ret = HYPERVISOR_xenoprof_op(XENOPROF_get_buffer, &get_buffer)) )
  18.295 +	sbuf->buffer = NULL;
  18.296 +	if ( (ret = HYPERVISOR_xenoprof_op(XENOPROF_get_buffer, get_buffer)) )
  18.297  		return ret;
  18.298  
  18.299 -	nbuf = get_buffer.nbuf;
  18.300 -	npages = (get_buffer.bufsize * nbuf - 1) / PAGE_SIZE + 1;
  18.301 +	npages = (get_buffer->bufsize * get_buffer->nbuf - 1) / PAGE_SIZE + 1;
  18.302  
  18.303  	area = alloc_vm_area(npages * PAGE_SIZE);
  18.304  	if (area == NULL)
  18.305 @@ -259,231 +93,55 @@ static int map_xenoprof_buffer(int max_s
  18.306  
  18.307  	if ( (ret = direct_kernel_remap_pfn_range(
  18.308  		      (unsigned long)area->addr,
  18.309 -		      get_buffer.buf_maddr >> PAGE_SHIFT,
  18.310 -		      npages * PAGE_SIZE, __pgprot(_KERNPG_TABLE), DOMID_SELF)) ) {
  18.311 +		      get_buffer->buf_gmaddr >> PAGE_SHIFT,
  18.312 +		      npages * PAGE_SIZE, __pgprot(_KERNPG_TABLE),
  18.313 +		      DOMID_SELF)) ) {
  18.314  		vunmap(area->addr);
  18.315  		return ret;
  18.316  	}
  18.317  
  18.318 -	shared_buffer = area->addr;
  18.319 -	for (i=0; i< nbuf; i++) {
  18.320 -		buf = (struct xenoprof_buf*) 
  18.321 -			&shared_buffer[i * get_buffer.bufsize];
  18.322 -		BUG_ON(buf->vcpu_id >= MAX_VIRT_CPUS);
  18.323 -		xenoprof_buf[buf->vcpu_id] = buf;
  18.324 -	}
  18.325 -
  18.326 -	return 0;
  18.327 -}
  18.328 -
  18.329 -
  18.330 -static int xenoprof_setup(void)
  18.331 -{
  18.332 -	int ret;
  18.333 -	int i;
  18.334 -
  18.335 -	if ( (ret = map_xenoprof_buffer(MAX_XENOPROF_SAMPLES)) )
  18.336 -		return ret;
  18.337 -
  18.338 -	if ( (ret = bind_virq()) )
  18.339 -		return ret;
  18.340 -
  18.341 -	if (is_primary) {
  18.342 -		struct xenoprof_counter counter;
  18.343 -
  18.344 -		/* Define dom0 as an active domain if not done yet */
  18.345 -		if (!active_defined) {
  18.346 -			domid_t domid;
  18.347 -			ret = HYPERVISOR_xenoprof_op(XENOPROF_reset_active_list, NULL);
  18.348 -			if (ret)
  18.349 -				goto err;
  18.350 -			domid = 0;
  18.351 -			ret = HYPERVISOR_xenoprof_op(XENOPROF_set_active, &domid);
  18.352 -			if (ret)
  18.353 -				goto err;
  18.354 -			active_defined = 1;
  18.355 -		}
  18.356 -
  18.357 -		ret = HYPERVISOR_xenoprof_op(XENOPROF_reserve_counters, NULL);
  18.358 -		if (ret)
  18.359 -			goto err;
  18.360 -		for (i=0; i<num_events; i++) {
  18.361 -			counter.ind       = i;
  18.362 -			counter.count     = (uint64_t)counter_config[i].count;
  18.363 -			counter.enabled   = (uint32_t)counter_config[i].enabled;
  18.364 -			counter.event     = (uint32_t)counter_config[i].event;
  18.365 -			counter.kernel    = (uint32_t)counter_config[i].kernel;
  18.366 -			counter.user      = (uint32_t)counter_config[i].user;
  18.367 -			counter.unit_mask = (uint64_t)counter_config[i].unit_mask;
  18.368 -			HYPERVISOR_xenoprof_op(XENOPROF_counter, 
  18.369 -					       &counter);
  18.370 -		}
  18.371 -		ret = HYPERVISOR_xenoprof_op(XENOPROF_setup_events, NULL);
  18.372 -
  18.373 -		if (ret)
  18.374 -			goto err;
  18.375 -	}
  18.376 -
  18.377 -	ret = HYPERVISOR_xenoprof_op(XENOPROF_enable_virq, NULL);
  18.378 -	if (ret)
  18.379 -		goto err;
  18.380 -
  18.381 -	xenoprof_enabled = 1;
  18.382 -	return 0;
  18.383 - err:
  18.384 -	unbind_virq();
  18.385 -	return ret;
  18.386 -}
  18.387 -
  18.388 -
  18.389 -static void xenoprof_shutdown(void)
  18.390 -{
  18.391 -	xenoprof_enabled = 0;
  18.392 -
  18.393 -	HYPERVISOR_xenoprof_op(XENOPROF_disable_virq, NULL);
  18.394 -
  18.395 -	if (is_primary) {
  18.396 -		HYPERVISOR_xenoprof_op(XENOPROF_release_counters, NULL);
  18.397 -		active_defined = 0;
  18.398 -	}
  18.399 -
  18.400 -	unbind_virq();
  18.401 -
  18.402 -}
  18.403 -
  18.404 -
  18.405 -static int xenoprof_start(void)
  18.406 -{
  18.407 -	int ret = 0;
  18.408 -
  18.409 -	if (is_primary)
  18.410 -		ret = HYPERVISOR_xenoprof_op(XENOPROF_start, NULL);
  18.411 -
  18.412 +	sbuf->buffer = area->addr;
  18.413  	return ret;
  18.414  }
  18.415  
  18.416 -
  18.417 -static void xenoprof_stop(void)
  18.418 -{
  18.419 -	if (is_primary)
  18.420 -		HYPERVISOR_xenoprof_op(XENOPROF_stop, NULL);
  18.421 -}
  18.422 -
  18.423 -
  18.424 -static int xenoprof_set_active(int * active_domains,
  18.425 -			       unsigned int adomains)
  18.426 -{
  18.427 -	int ret = 0;
  18.428 -	int i;
  18.429 -	int set_dom0 = 0;
  18.430 -	domid_t domid;
  18.431 -
  18.432 -	if (!is_primary)
  18.433 -		return 0;
  18.434 -
  18.435 -	if (adomains > MAX_OPROF_DOMAINS)
  18.436 -		return -E2BIG;
  18.437 -
  18.438 -	ret = HYPERVISOR_xenoprof_op(XENOPROF_reset_active_list, NULL);
  18.439 -	if (ret)
  18.440 -		return ret;
  18.441 -
  18.442 -	for (i=0; i<adomains; i++) {
  18.443 -		domid = active_domains[i];
  18.444 -		if (domid != active_domains[i]) {
  18.445 -			ret = -EINVAL;
  18.446 -			goto out;
  18.447 -		}
  18.448 -		ret = HYPERVISOR_xenoprof_op(XENOPROF_set_active, &domid);
  18.449 -		if (ret)
  18.450 -			goto out;
  18.451 -		if (active_domains[i] == 0)
  18.452 -			set_dom0 = 1;
  18.453 -	}
  18.454 -	/* dom0 must always be active but may not be in the list */ 
  18.455 -	if (!set_dom0) {
  18.456 -		domid = 0;
  18.457 -		ret = HYPERVISOR_xenoprof_op(XENOPROF_set_active, &domid);
  18.458 -	}
  18.459 -
  18.460 -out:
  18.461 -	if (ret)
  18.462 -		HYPERVISOR_xenoprof_op(XENOPROF_reset_active_list, NULL);
  18.463 -	active_defined = !ret;
  18.464 -	return ret;
  18.465 -}
  18.466 -
  18.467 -static int xenoprof_set_passive(int * p_domains,
  18.468 -                                unsigned int pdoms)
  18.469 +int xenoprof_arch_set_passive(struct xenoprof_passive * pdomain,
  18.470 +			      struct xenoprof_shared_buffer * sbuf)
  18.471  {
  18.472  	int ret;
  18.473 -	int i, j;
  18.474  	int npages;
  18.475 -	struct xenoprof_buf *buf;
  18.476  	struct vm_struct *area;
  18.477  	pgprot_t prot = __pgprot(_KERNPG_TABLE);
  18.478  
  18.479 -	if (!is_primary)
  18.480 -        	return 0;
  18.481 -
  18.482 -	if (pdoms > MAX_OPROF_DOMAINS)
  18.483 -		return -E2BIG;
  18.484 -
  18.485 -	ret = HYPERVISOR_xenoprof_op(XENOPROF_reset_passive_list, NULL);
  18.486 +	sbuf->buffer = NULL;
  18.487 +	ret = HYPERVISOR_xenoprof_op(XENOPROF_set_passive, pdomain);
  18.488  	if (ret)
  18.489 -		return ret;
  18.490 -
  18.491 -	for (i = 0; i < pdoms; i++) {
  18.492 -		passive_domains[i].domain_id = p_domains[i];
  18.493 -		passive_domains[i].max_samples = 2048;
  18.494 -		ret = HYPERVISOR_xenoprof_op(XENOPROF_set_passive,
  18.495 -					     &passive_domains[i]);
  18.496 -		if (ret)
  18.497 -			goto out;
  18.498 -
  18.499 -		npages = (passive_domains[i].bufsize * passive_domains[i].nbuf - 1) / PAGE_SIZE + 1;
  18.500 +		goto out;
  18.501  
  18.502 -		area = alloc_vm_area(npages * PAGE_SIZE);
  18.503 -		if (area == NULL) {
  18.504 -			ret = -ENOMEM;
  18.505 -			goto out;
  18.506 -		}
  18.507 +	npages = (pdomain->bufsize * pdomain->nbuf - 1) / PAGE_SIZE + 1;
  18.508  
  18.509 -		ret = direct_kernel_remap_pfn_range(
  18.510 -			(unsigned long)area->addr,
  18.511 -			passive_domains[i].buf_maddr >> PAGE_SHIFT,
  18.512 -			npages * PAGE_SIZE, prot, DOMID_SELF);
  18.513 -		if (ret) {
  18.514 -			vunmap(area->addr);
  18.515 -			goto out;
  18.516 -		}
  18.517 -
  18.518 -		p_shared_buffer[i] = area->addr;
  18.519 -
  18.520 -		for (j = 0; j < passive_domains[i].nbuf; j++) {
  18.521 -			buf = (struct xenoprof_buf *)
  18.522 -				&p_shared_buffer[i][j * passive_domains[i].bufsize];
  18.523 -			BUG_ON(buf->vcpu_id >= MAX_VIRT_CPUS);
  18.524 -			p_xenoprof_buf[i][buf->vcpu_id] = buf;
  18.525 -		}
  18.526 -
  18.527 +	area = alloc_vm_area(npages * PAGE_SIZE);
  18.528 +	if (area == NULL) {
  18.529 +		ret = -ENOMEM;
  18.530 +		goto out;
  18.531  	}
  18.532  
  18.533 -	pdomains = pdoms;
  18.534 -	return 0;
  18.535 +	ret = direct_kernel_remap_pfn_range(
  18.536 +		(unsigned long)area->addr,
  18.537 +		pdomain->buf_gmaddr >> PAGE_SHIFT,
  18.538 +		npages * PAGE_SIZE, prot, DOMID_SELF);
  18.539 +	if (ret) {
  18.540 +		vunmap(area->addr);
  18.541 +		goto out;
  18.542 +	}
  18.543 +	sbuf->buffer = area->addr;
  18.544  
  18.545  out:
  18.546 -	for (j = 0; j < i; j++) {
  18.547 -		vunmap(p_shared_buffer[j]);
  18.548 -		p_shared_buffer[j] = NULL;
  18.549 -	}
  18.550 -
  18.551 - 	return ret;
  18.552 +	return ret;
  18.553  }
  18.554  
  18.555  struct op_counter_config counter_config[OP_MAX_COUNTER];
  18.556  
  18.557 -static int xenoprof_create_files(struct super_block * sb, struct dentry * root)
  18.558 +int xenoprof_create_files(struct super_block * sb, struct dentry * root)
  18.559  {
  18.560  	unsigned int i;
  18.561  
  18.562 @@ -510,75 +168,12 @@ static int xenoprof_create_files(struct 
  18.563  	return 0;
  18.564  }
  18.565  
  18.566 -
  18.567 -struct oprofile_operations xenoprof_ops = {
  18.568 -	.create_files 	= xenoprof_create_files,
  18.569 -	.set_active	= xenoprof_set_active,
  18.570 -	.set_passive    = xenoprof_set_passive,
  18.571 -	.setup 		= xenoprof_setup,
  18.572 -	.shutdown	= xenoprof_shutdown,
  18.573 -	.start		= xenoprof_start,
  18.574 -	.stop		= xenoprof_stop
  18.575 -};
  18.576 -
  18.577 -
  18.578 -/* in order to get driverfs right */
  18.579 -static int using_xenoprof;
  18.580 -
  18.581  int __init oprofile_arch_init(struct oprofile_operations * ops)
  18.582  {
  18.583 -	struct xenoprof_init init;
  18.584 -	int ret, i;
  18.585 -
  18.586 -	ret = HYPERVISOR_xenoprof_op(XENOPROF_init, &init);
  18.587 -
  18.588 -	if (!ret) {
  18.589 -		num_events = init.num_events;
  18.590 -		is_primary = init.is_primary;
  18.591 -
  18.592 -		/* just in case - make sure we do not overflow event list 
  18.593 -		   (i.e. counter_config list) */
  18.594 -		if (num_events > OP_MAX_COUNTER)
  18.595 -			num_events = OP_MAX_COUNTER;
  18.596 -
  18.597 -		/*  cpu_type is detected by Xen */
  18.598 -		cpu_type[XENOPROF_CPU_TYPE_SIZE-1] = 0;
  18.599 -		strncpy(cpu_type, init.cpu_type, XENOPROF_CPU_TYPE_SIZE - 1);
  18.600 -		xenoprof_ops.cpu_type = cpu_type;
  18.601 -
  18.602 -		init_driverfs();
  18.603 -		using_xenoprof = 1;
  18.604 -		*ops = xenoprof_ops;
  18.605 -
  18.606 -		for (i=0; i<NR_CPUS; i++)
  18.607 -			ovf_irq[i] = -1;
  18.608 -
  18.609 -		active_defined = 0;
  18.610 -	}
  18.611 -	printk(KERN_INFO "oprofile_arch_init: ret %d, events %d, "
  18.612 -	       "is_primary %d\n", ret, num_events, is_primary);
  18.613 -	return ret;
  18.614 +	return xenoprofile_init(ops);
  18.615  }
  18.616  
  18.617 -
  18.618 -void __exit oprofile_arch_exit(void)
  18.619 +void oprofile_arch_exit(void)
  18.620  {
  18.621 -	int i;
  18.622 -
  18.623 -	if (using_xenoprof)
  18.624 -		exit_driverfs();
  18.625 -
  18.626 -	if (shared_buffer) {
  18.627 -		vunmap(shared_buffer);
  18.628 -		shared_buffer = NULL;
  18.629 -	}
  18.630 -	if (is_primary) {
  18.631 -		for (i = 0; i < pdomains; i++)
  18.632 -			if (p_shared_buffer[i]) {
  18.633 -		                vunmap(p_shared_buffer[i]);
  18.634 -                		p_shared_buffer[i] = NULL;
  18.635 -			}
  18.636 -		HYPERVISOR_xenoprof_op(XENOPROF_shutdown, NULL);
  18.637 -        }
  18.638 -
  18.639 +	xenoprofile_exit();
  18.640  }
    19.1 --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/acpi/Makefile	Mon Nov 27 10:10:57 2006 -0700
    19.2 +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/acpi/Makefile	Tue Nov 28 10:37:36 2006 -0700
    19.3 @@ -4,6 +4,7 @@ obj-$(CONFIG_ACPI_SLEEP)	+= sleep.o wake
    19.4  
    19.5  ifneq ($(CONFIG_ACPI_PROCESSOR),)
    19.6  obj-y			+= processor.o
    19.7 +processor-y		:= ../../../i386/kernel/acpi/processor.o ../../../i386/kernel/acpi/cstate.o
    19.8  endif
    19.9  
   19.10  boot-$(CONFIG_XEN)		:= ../../../i386/kernel/acpi/boot-xen.o
    20.1 --- a/linux-2.6-xen-sparse/arch/x86_64/oprofile/Makefile	Mon Nov 27 10:10:57 2006 -0700
    20.2 +++ b/linux-2.6-xen-sparse/arch/x86_64/oprofile/Makefile	Tue Nov 28 10:37:36 2006 -0700
    20.3 @@ -12,6 +12,8 @@ DRIVER_OBJS = $(addprefix ../../../drive
    20.4  	timer_int.o )
    20.5  
    20.6  ifdef CONFIG_XEN
    20.7 +XENOPROF_COMMON_OBJS = $(addprefix ../../../drivers/xen/xenoprof/, \
    20.8 +			 xenoprofile.o)
    20.9  OPROFILE-y := xenoprof.o
   20.10  else
   20.11  OPROFILE-y := init.o backtrace.o
   20.12 @@ -19,4 +21,5 @@ OPROFILE-$(CONFIG_X86_LOCAL_APIC) += nmi
   20.13  				     op_model_ppro.o
   20.14  OPROFILE-$(CONFIG_X86_IO_APIC)    += nmi_timer_int.o 
   20.15  endif
   20.16 -oprofile-y = $(DRIVER_OBJS) $(addprefix ../../i386/oprofile/, $(OPROFILE-y))
   20.17 +oprofile-y = $(DRIVER_OBJS) $(XENOPROF_COMMON_OBJS) \
   20.18 +	     $(addprefix ../../i386/oprofile/, $(OPROFILE-y))
    21.1 --- a/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c	Mon Nov 27 10:10:57 2006 -0700
    21.2 +++ b/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c	Tue Nov 28 10:37:36 2006 -0700
    21.3 @@ -215,9 +215,7 @@ static int increase_reservation(unsigned
    21.4  		BUG_ON(!xen_feature(XENFEAT_auto_translated_physmap) &&
    21.5  		       phys_to_machine_mapping_valid(pfn));
    21.6  
    21.7 -		/* Update P->M and M->P tables. */
    21.8  		set_phys_to_machine(pfn, frame_list[i]);
    21.9 -		xen_machphys_update(frame_list[i], pfn);
   21.10  
   21.11  		/* Link back into the page tables if not highmem. */
   21.12  		if (pfn < max_low_pfn) {
    22.1 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/common.h	Mon Nov 27 10:10:57 2006 -0700
    22.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/common.h	Tue Nov 28 10:37:36 2006 -0700
    22.3 @@ -113,7 +113,7 @@ int vbd_create(blkif_t *blkif, blkif_vde
    22.4  	       unsigned minor, int readonly);
    22.5  void vbd_free(struct vbd *vbd);
    22.6  
    22.7 -unsigned long vbd_size(struct vbd *vbd);
    22.8 +unsigned long long vbd_size(struct vbd *vbd);
    22.9  unsigned int vbd_info(struct vbd *vbd);
   22.10  unsigned long vbd_secsize(struct vbd *vbd);
   22.11  
    23.1 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/vbd.c	Mon Nov 27 10:10:57 2006 -0700
    23.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/vbd.c	Tue Nov 28 10:37:36 2006 -0700
    23.3 @@ -35,7 +35,7 @@
    23.4  #define vbd_sz(_v)   ((_v)->bdev->bd_part ?				\
    23.5  	(_v)->bdev->bd_part->nr_sects : (_v)->bdev->bd_disk->capacity)
    23.6  
    23.7 -unsigned long vbd_size(struct vbd *vbd)
    23.8 +unsigned long long vbd_size(struct vbd *vbd)
    23.9  {
   23.10  	return vbd_sz(vbd);
   23.11  }
    24.1 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c	Mon Nov 27 10:10:57 2006 -0700
    24.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c	Tue Nov 28 10:37:36 2006 -0700
    24.3 @@ -389,7 +389,7 @@ again:
    24.4  	if (err)
    24.5  		goto abort;
    24.6  
    24.7 -	err = xenbus_printf(xbt, dev->nodename, "sectors", "%lu",
    24.8 +	err = xenbus_printf(xbt, dev->nodename, "sectors", "%llu",
    24.9  			    vbd_size(&be->blkif->vbd));
   24.10  	if (err) {
   24.11  		xenbus_dev_fatal(dev, err, "writing %s/sectors",
    25.1 --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c	Mon Nov 27 10:10:57 2006 -0700
    25.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c	Tue Nov 28 10:37:36 2006 -0700
    25.3 @@ -138,10 +138,10 @@ static int blkfront_resume(struct xenbus
    25.4  
    25.5  	DPRINTK("blkfront_resume: %s\n", dev->nodename);
    25.6  
    25.7 -	blkif_free(info, 1);
    25.8 +	blkif_free(info, info->connected == BLKIF_STATE_CONNECTED);
    25.9  
   25.10  	err = talk_to_backend(dev, info);
   25.11 -	if (!err)
   25.12 +	if (info->connected == BLKIF_STATE_SUSPENDED && !err)
   25.13  		blkif_recover(info);
   25.14  
   25.15  	return err;
   25.16 @@ -298,7 +298,8 @@ static void backend_changed(struct xenbu
   25.17   */
   25.18  static void connect(struct blkfront_info *info)
   25.19  {
   25.20 -	unsigned long sectors, sector_size;
   25.21 +	unsigned long long sectors;
   25.22 +	unsigned long sector_size;
   25.23  	unsigned int binfo;
   25.24  	int err;
   25.25  
   25.26 @@ -309,7 +310,7 @@ static void connect(struct blkfront_info
   25.27  	DPRINTK("blkfront.c:connect:%s.\n", info->xbdev->otherend);
   25.28  
   25.29  	err = xenbus_gather(XBT_NIL, info->xbdev->otherend,
   25.30 -			    "sectors", "%lu", &sectors,
   25.31 +			    "sectors", "%llu", &sectors,
   25.32  			    "info", "%u", &binfo,
   25.33  			    "sector-size", "%lu", &sector_size,
   25.34  			    NULL);
    26.1 --- a/linux-2.6-xen-sparse/drivers/xen/char/mem.c	Mon Nov 27 10:10:57 2006 -0700
    26.2 +++ b/linux-2.6-xen-sparse/drivers/xen/char/mem.c	Tue Nov 28 10:37:36 2006 -0700
    26.3 @@ -28,13 +28,12 @@
    26.4  #include <asm/io.h>
    26.5  #include <asm/hypervisor.h>
    26.6  
    26.7 -static inline int uncached_access(struct file *file)
    26.8 +#ifndef ARCH_HAS_VALID_PHYS_ADDR_RANGE
    26.9 +static inline int valid_phys_addr_range(unsigned long addr, size_t *count)
   26.10  {
   26.11 -	if (file->f_flags & O_SYNC)
   26.12 -		return 1;
   26.13 -	/* Xen sets correct MTRR type on non-RAM for us. */
   26.14 -	return 0;
   26.15 +	return 1;
   26.16  }
   26.17 +#endif
   26.18  
   26.19  /*
   26.20   * This funcion reads the *physical* memory. The f_pos points directly to the 
   26.21 @@ -47,6 +46,9 @@ static ssize_t read_mem(struct file * fi
   26.22  	ssize_t read = 0, sz;
   26.23  	void __iomem *v;
   26.24  
   26.25 +	if (!valid_phys_addr_range(p, &count))
   26.26 +		return -EFAULT;
   26.27 +
   26.28  	while (count > 0) {
   26.29  		/*
   26.30  		 * Handle first page in case it's not aligned
   26.31 @@ -58,13 +60,15 @@ static ssize_t read_mem(struct file * fi
   26.32  
   26.33  		sz = min_t(unsigned long, sz, count);
   26.34  
   26.35 -		if ((v = ioremap(p, sz)) == NULL) {
   26.36 +		v = xlate_dev_mem_ptr(p, sz);
   26.37 +		if (IS_ERR(v) || v == NULL) {
   26.38  			/*
   26.39 -			 * Some programs (e.g., dmidecode) groove off into weird RAM
   26.40 -			 * areas where no tables can possibly exist (because Xen will
   26.41 -			 * have stomped on them!). These programs get rather upset if
   26.42 -			 * we let them know that Xen failed their access, so we fake
   26.43 -			 * out a read of all zeroes. :-)
   26.44 +			 * Some programs (e.g., dmidecode) groove off into
   26.45 +			 * weird RAM areas where no tables can possibly exist
   26.46 +			 * (because Xen will have stomped on them!). These
   26.47 +			 * programs get rather upset if we let them know that
   26.48 +			 * Xen failed their access, so we fake out a read of
   26.49 +			 * all zeroes.
   26.50  			 */
   26.51  			if (clear_user(buf, count))
   26.52  				return -EFAULT;
   26.53 @@ -73,7 +77,7 @@ static ssize_t read_mem(struct file * fi
   26.54  		}
   26.55  
   26.56  		ignored = copy_to_user(buf, v, sz);
   26.57 -		iounmap(v);
   26.58 +		xlate_dev_mem_ptr_unmap(v);
   26.59  		if (ignored)
   26.60  			return -EFAULT;
   26.61  		buf += sz;
   26.62 @@ -93,6 +97,9 @@ static ssize_t write_mem(struct file * f
   26.63  	ssize_t written = 0, sz;
   26.64  	void __iomem *v;
   26.65  
   26.66 +	if (!valid_phys_addr_range(p, &count))
   26.67 +		return -EFAULT;
   26.68 +
   26.69  	while (count > 0) {
   26.70  		/*
   26.71  		 * Handle first page in case it's not aligned
   26.72 @@ -104,11 +111,17 @@ static ssize_t write_mem(struct file * f
   26.73  
   26.74  		sz = min_t(unsigned long, sz, count);
   26.75  
   26.76 -		if ((v = ioremap(p, sz)) == NULL)
   26.77 +		v = xlate_dev_mem_ptr(p, sz);
   26.78 +		if (v == NULL)
   26.79  			break;
   26.80 +		if (IS_ERR(v)) {
   26.81 +			if (written == 0)
   26.82 +				return PTR_ERR(v);
   26.83 +			break;
   26.84 +		}
   26.85  
   26.86  		ignored = copy_from_user(v, buf, sz);
   26.87 -		iounmap(v);
   26.88 +		xlate_dev_mem_ptr_unmap(v);
   26.89  		if (ignored) {
   26.90  			written += sz - ignored;
   26.91  			if (written)
   26.92 @@ -125,6 +138,15 @@ static ssize_t write_mem(struct file * f
   26.93  	return written;
   26.94  }
   26.95  
   26.96 +#ifndef ARCH_HAS_DEV_MEM_MMAP_MEM
   26.97 +static inline int uncached_access(struct file *file)
   26.98 +{
   26.99 +	if (file->f_flags & O_SYNC)
  26.100 +		return 1;
  26.101 +	/* Xen sets correct MTRR type on non-RAM for us. */
  26.102 +	return 0;
  26.103 +}
  26.104 +
  26.105  static int mmap_mem(struct file * file, struct vm_area_struct * vma)
  26.106  {
  26.107  	size_t size = vma->vm_end - vma->vm_start;
  26.108 @@ -136,6 +158,7 @@ static int mmap_mem(struct file * file, 
  26.109  	return direct_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
  26.110  				      size, vma->vm_page_prot, DOMID_IO);
  26.111  }
  26.112 +#endif
  26.113  
  26.114  /*
  26.115   * The memory devices use the full 32/64 bits of the offset, and so we cannot
    27.1 --- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c	Mon Nov 27 10:10:57 2006 -0700
    27.2 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c	Tue Nov 28 10:37:36 2006 -0700
    27.3 @@ -494,7 +494,7 @@ static int netbk_check_gop(int nr_frags,
    27.4  			copy_op = npo->copy + npo->copy_cons++;
    27.5  			if (copy_op->status != GNTST_okay) {
    27.6  				DPRINTK("Bad status %d from copy to DOM%d.\n",
    27.7 -					gop->status, domid);
    27.8 +					copy_op->status, domid);
    27.9  				status = NETIF_RSP_ERROR;
   27.10  			}
   27.11  		} else {
    28.1 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_client.c	Mon Nov 27 10:10:57 2006 -0700
    28.2 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_client.c	Tue Nov 28 10:37:36 2006 -0700
    28.3 @@ -39,9 +39,6 @@
    28.4  #include <xen/platform-compat.h>
    28.5  #endif
    28.6  
    28.7 -/* xenbus_probe.c */
    28.8 -extern char *kasprintf(const char *fmt, ...);
    28.9 -
   28.10  #define DPRINTK(fmt, args...) \
   28.11      pr_debug("xenbus_client (%s:%d) " fmt ".\n", __FUNCTION__, __LINE__, ##args)
   28.12  
   28.13 @@ -88,7 +85,7 @@ int xenbus_watch_path2(struct xenbus_dev
   28.14  					const char **, unsigned int))
   28.15  {
   28.16  	int err;
   28.17 -	char *state = kasprintf("%s/%s", path, path2);
   28.18 +	char *state = kasprintf(GFP_KERNEL, "%s/%s", path, path2);
   28.19  	if (!state) {
   28.20  		xenbus_dev_fatal(dev, -ENOMEM, "allocating path for watch");
   28.21  		return -ENOMEM;
   28.22 @@ -156,7 +153,7 @@ EXPORT_SYMBOL_GPL(xenbus_frontend_closed
   28.23   */
   28.24  static char *error_path(struct xenbus_device *dev)
   28.25  {
   28.26 -	return kasprintf("error/%s", dev->nodename);
   28.27 +	return kasprintf(GFP_KERNEL, "error/%s", dev->nodename);
   28.28  }
   28.29  
   28.30  
    29.1 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c	Mon Nov 27 10:10:57 2006 -0700
    29.2 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c	Tue Nov 28 10:37:36 2006 -0700
    29.3 @@ -444,27 +444,6 @@ static void xenbus_dev_release(struct de
    29.4  		kfree(to_xenbus_device(dev));
    29.5  }
    29.6  
    29.7 -/* Simplified asprintf. */
    29.8 -char *kasprintf(const char *fmt, ...)
    29.9 -{
   29.10 -	va_list ap;
   29.11 -	unsigned int len;
   29.12 -	char *p, dummy[1];
   29.13 -
   29.14 -	va_start(ap, fmt);
   29.15 -	/* FIXME: vsnprintf has a bug, NULL should work */
   29.16 -	len = vsnprintf(dummy, 0, fmt, ap);
   29.17 -	va_end(ap);
   29.18 -
   29.19 -	p = kmalloc(len + 1, GFP_KERNEL);
   29.20 -	if (!p)
   29.21 -		return NULL;
   29.22 -	va_start(ap, fmt);
   29.23 -	vsprintf(p, fmt, ap);
   29.24 -	va_end(ap);
   29.25 -	return p;
   29.26 -}
   29.27 -
   29.28  static ssize_t xendev_show_nodename(struct device *dev,
   29.29  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13)
   29.30  				    struct device_attribute *attr,
   29.31 @@ -547,7 +526,7 @@ static int xenbus_probe_frontend(const c
   29.32  	char *nodename;
   29.33  	int err;
   29.34  
   29.35 -	nodename = kasprintf("%s/%s/%s", xenbus_frontend.root, type, name);
   29.36 +	nodename = kasprintf(GFP_KERNEL, "%s/%s/%s", xenbus_frontend.root, type, name);
   29.37  	if (!nodename)
   29.38  		return -ENOMEM;
   29.39  
   29.40 @@ -644,7 +623,7 @@ void dev_changed(const char *node, struc
   29.41  	rootlen = strsep_len(node, '/', bus->levels);
   29.42  	if (rootlen < 0)
   29.43  		return;
   29.44 -	root = kasprintf("%.*s", rootlen, node);
   29.45 +	root = kasprintf(GFP_KERNEL, "%.*s", rootlen, node);
   29.46  	if (!root)
   29.47  		return;
   29.48  
    30.1 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.h	Mon Nov 27 10:10:57 2006 -0700
    30.2 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.h	Tue Nov 28 10:37:36 2006 -0700
    30.3 @@ -70,8 +70,5 @@ extern int xenbus_probe_devices(struct x
    30.4  
    30.5  extern void dev_changed(const char *node, struct xen_bus_type *bus);
    30.6  
    30.7 -/* Simplified asprintf. Probably belongs in lib */
    30.8 -extern char *kasprintf(const char *fmt, ...);
    30.9 -
   30.10  #endif
   30.11  
    31.1 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe_backend.c	Mon Nov 27 10:10:57 2006 -0700
    31.2 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe_backend.c	Tue Nov 28 10:37:36 2006 -0700
    31.3 @@ -188,7 +188,7 @@ static int xenbus_probe_backend_unit(con
    31.4  	char *nodename;
    31.5  	int err;
    31.6  
    31.7 -	nodename = kasprintf("%s/%s", dir, name);
    31.8 +	nodename = kasprintf(GFP_KERNEL, "%s/%s", dir, name);
    31.9  	if (!nodename)
   31.10  		return -ENOMEM;
   31.11  
   31.12 @@ -209,7 +209,7 @@ static int xenbus_probe_backend(const ch
   31.13  
   31.14  	DPRINTK("");
   31.15  
   31.16 -	nodename = kasprintf("%s/%s/%s", xenbus_backend.root, type, domid);
   31.17 +	nodename = kasprintf(GFP_KERNEL, "%s/%s/%s", xenbus_backend.root, type, domid);
   31.18  	if (!nodename)
   31.19  		return -ENOMEM;
   31.20  
    32.1 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c	Mon Nov 27 10:10:57 2006 -0700
    32.2 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c	Tue Nov 28 10:37:36 2006 -0700
    32.3 @@ -51,9 +51,6 @@
    32.4  #include <xen/platform-compat.h>
    32.5  #endif
    32.6  
    32.7 -/* xenbus_probe.c */
    32.8 -extern char *kasprintf(const char *fmt, ...);
    32.9 -
   32.10  struct xs_stored_msg {
   32.11  	struct list_head list;
   32.12  
   32.13 @@ -295,9 +292,9 @@ static char *join(const char *dir, const
   32.14  	char *buffer;
   32.15  
   32.16  	if (strlen(name) == 0)
   32.17 -		buffer = kasprintf("%s", dir);
   32.18 +		buffer = kasprintf(GFP_KERNEL, "%s", dir);
   32.19  	else
   32.20 -		buffer = kasprintf("%s/%s", dir, name);
   32.21 +		buffer = kasprintf(GFP_KERNEL, "%s/%s", dir, name);
   32.22  	return (!buffer) ? ERR_PTR(-ENOMEM) : buffer;
   32.23  }
   32.24  
    33.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.2 +++ b/linux-2.6-xen-sparse/drivers/xen/xenoprof/xenoprofile.c	Tue Nov 28 10:37:36 2006 -0700
    33.3 @@ -0,0 +1,500 @@
    33.4 +/**
    33.5 + * @file xenoprofile.c
    33.6 + *
    33.7 + * @remark Copyright 2002 OProfile authors
    33.8 + * @remark Read the file COPYING
    33.9 + *
   33.10 + * @author John Levon <levon@movementarian.org>
   33.11 + *
   33.12 + * Modified by Aravind Menon and Jose Renato Santos for Xen
   33.13 + * These modifications are:
   33.14 + * Copyright (C) 2005 Hewlett-Packard Co.
   33.15 + *
   33.16 + * Separated out arch-generic part
   33.17 + * Copyright (c) 2006 Isaku Yamahata <yamahata at valinux co jp>
   33.18 + *                    VA Linux Systems Japan K.K.
   33.19 + */
   33.20 +
   33.21 +#include <linux/init.h>
   33.22 +#include <linux/notifier.h>
   33.23 +#include <linux/smp.h>
   33.24 +#include <linux/oprofile.h>
   33.25 +#include <linux/sysdev.h>
   33.26 +#include <linux/slab.h>
   33.27 +#include <linux/interrupt.h>
   33.28 +#include <linux/vmalloc.h>
   33.29 +#include <asm/pgtable.h>
   33.30 +#include <xen/evtchn.h>
   33.31 +#include <xen/xenoprof.h>
   33.32 +#include <xen/driver_util.h>
   33.33 +#include <xen/interface/xen.h>
   33.34 +#include <xen/interface/xenoprof.h>
   33.35 +#include "../../../drivers/oprofile/cpu_buffer.h"
   33.36 +#include "../../../drivers/oprofile/event_buffer.h"
   33.37 +
   33.38 +#define MAX_XENOPROF_SAMPLES 16
   33.39 +
   33.40 +/* sample buffers shared with Xen */
   33.41 +xenoprof_buf_t * xenoprof_buf[MAX_VIRT_CPUS];
   33.42 +/* Shared buffer area */
   33.43 +struct xenoprof_shared_buffer shared_buffer;
   33.44 +
   33.45 +/* Passive sample buffers shared with Xen */
   33.46 +xenoprof_buf_t *p_xenoprof_buf[MAX_OPROF_DOMAINS][MAX_VIRT_CPUS];
   33.47 +/* Passive shared buffer area */
   33.48 +struct xenoprof_shared_buffer p_shared_buffer[MAX_OPROF_DOMAINS];
   33.49 +
   33.50 +static int xenoprof_start(void);
   33.51 +static void xenoprof_stop(void);
   33.52 +
   33.53 +static int xenoprof_enabled = 0;
   33.54 +static int xenoprof_is_primary = 0;
   33.55 +static int active_defined;
   33.56 +
   33.57 +/* Number of buffers in shared area (one per VCPU) */
   33.58 +int nbuf;
   33.59 +/* Mappings of VIRQ_XENOPROF to irq number (per cpu) */
   33.60 +int ovf_irq[NR_CPUS];
   33.61 +/* cpu model type string - copied from Xen memory space on XENOPROF_init command */
   33.62 +char cpu_type[XENOPROF_CPU_TYPE_SIZE];
   33.63 +
   33.64 +#ifdef CONFIG_PM
   33.65 +
   33.66 +static int xenoprof_suspend(struct sys_device * dev, pm_message_t state)
   33.67 +{
   33.68 +	if (xenoprof_enabled == 1)
   33.69 +		xenoprof_stop();
   33.70 +	return 0;
   33.71 +}
   33.72 +
   33.73 +
   33.74 +static int xenoprof_resume(struct sys_device * dev)
   33.75 +{
   33.76 +	if (xenoprof_enabled == 1)
   33.77 +		xenoprof_start();
   33.78 +	return 0;
   33.79 +}
   33.80 +
   33.81 +
   33.82 +static struct sysdev_class oprofile_sysclass = {
   33.83 +	set_kset_name("oprofile"),
   33.84 +	.resume		= xenoprof_resume,
   33.85 +	.suspend	= xenoprof_suspend
   33.86 +};
   33.87 +
   33.88 +
   33.89 +static struct sys_device device_oprofile = {
   33.90 +	.id	= 0,
   33.91 +	.cls	= &oprofile_sysclass,
   33.92 +};
   33.93 +
   33.94 +
   33.95 +static int __init init_driverfs(void)
   33.96 +{
   33.97 +	int error;
   33.98 +	if (!(error = sysdev_class_register(&oprofile_sysclass)))
   33.99 +		error = sysdev_register(&device_oprofile);
  33.100 +	return error;
  33.101 +}
  33.102 +
  33.103 +
  33.104 +static void exit_driverfs(void)
  33.105 +{
  33.106 +	sysdev_unregister(&device_oprofile);
  33.107 +	sysdev_class_unregister(&oprofile_sysclass);
  33.108 +}
  33.109 +
  33.110 +#else
  33.111 +#define init_driverfs() do { } while (0)
  33.112 +#define exit_driverfs() do { } while (0)
  33.113 +#endif /* CONFIG_PM */
  33.114 +
  33.115 +unsigned long long oprofile_samples = 0;
  33.116 +unsigned long long p_oprofile_samples = 0;
  33.117 +
  33.118 +unsigned int pdomains;
  33.119 +struct xenoprof_passive passive_domains[MAX_OPROF_DOMAINS];
  33.120 +
  33.121 +static void xenoprof_add_pc(xenoprof_buf_t *buf, int is_passive)
  33.122 +{
  33.123 +	int head, tail, size;
  33.124 +
  33.125 +	head = buf->event_head;
  33.126 +	tail = buf->event_tail;
  33.127 +	size = buf->event_size;
  33.128 +
  33.129 +	if (tail > head) {
  33.130 +		while (tail < size) {
  33.131 +			oprofile_add_pc(buf->event_log[tail].eip,
  33.132 +					buf->event_log[tail].mode,
  33.133 +					buf->event_log[tail].event);
  33.134 +			if (!is_passive)
  33.135 +				oprofile_samples++;
  33.136 +			else
  33.137 +				p_oprofile_samples++;
  33.138 +			tail++;
  33.139 +		}
  33.140 +		tail = 0;
  33.141 +	}
  33.142 +	while (tail < head) {
  33.143 +		oprofile_add_pc(buf->event_log[tail].eip,
  33.144 +				buf->event_log[tail].mode,
  33.145 +				buf->event_log[tail].event);
  33.146 +		if (!is_passive)
  33.147 +			oprofile_samples++;
  33.148 +		else
  33.149 +			p_oprofile_samples++;
  33.150 +		tail++;
  33.151 +	}
  33.152 +
  33.153 +	buf->event_tail = tail;
  33.154 +}
  33.155 +
  33.156 +static void xenoprof_handle_passive(void)
  33.157 +{
  33.158 +	int i, j;
  33.159 +	int flag_domain, flag_switch = 0;
  33.160 +	
  33.161 +	for (i = 0; i < pdomains; i++) {
  33.162 +		flag_domain = 0;
  33.163 +		for (j = 0; j < passive_domains[i].nbuf; j++) {
  33.164 +			xenoprof_buf_t *buf = p_xenoprof_buf[i][j];
  33.165 +			if (buf->event_head == buf->event_tail)
  33.166 +				continue;
  33.167 +			if (!flag_domain) {
  33.168 +				if (!oprofile_add_domain_switch(passive_domains[i].
  33.169 +								domain_id))
  33.170 +					goto done;
  33.171 +				flag_domain = 1;
  33.172 +			}
  33.173 +			xenoprof_add_pc(buf, 1);
  33.174 +			flag_switch = 1;
  33.175 +		}
  33.176 +	}
  33.177 +done:
  33.178 +	if (flag_switch)
  33.179 +		oprofile_add_domain_switch(COORDINATOR_DOMAIN);
  33.180 +}
  33.181 +
  33.182 +static irqreturn_t 
  33.183 +xenoprof_ovf_interrupt(int irq, void * dev_id, struct pt_regs * regs)
  33.184 +{
  33.185 +	struct xenoprof_buf * buf;
  33.186 +	int cpu;
  33.187 +	static unsigned long flag;
  33.188 +
  33.189 +	cpu = smp_processor_id();
  33.190 +	buf = xenoprof_buf[cpu];
  33.191 +
  33.192 +	xenoprof_add_pc(buf, 0);
  33.193 +
  33.194 +	if (xenoprof_is_primary && !test_and_set_bit(0, &flag)) {
  33.195 +		xenoprof_handle_passive();
  33.196 +		smp_mb__before_clear_bit();
  33.197 +		clear_bit(0, &flag);
  33.198 +	}
  33.199 +
  33.200 +	return IRQ_HANDLED;
  33.201 +}
  33.202 +
  33.203 +
  33.204 +static void unbind_virq(void)
  33.205 +{
  33.206 +	int i;
  33.207 +
  33.208 +	for_each_online_cpu(i) {
  33.209 +		if (ovf_irq[i] >= 0) {
  33.210 +			unbind_from_irqhandler(ovf_irq[i], NULL);
  33.211 +			ovf_irq[i] = -1;
  33.212 +		}
  33.213 +	}
  33.214 +}
  33.215 +
  33.216 +
  33.217 +static int bind_virq(void)
  33.218 +{
  33.219 +	int i, result;
  33.220 +
  33.221 +	for_each_online_cpu(i) {
  33.222 +		result = bind_virq_to_irqhandler(VIRQ_XENOPROF,
  33.223 +						 i,
  33.224 +						 xenoprof_ovf_interrupt,
  33.225 +						 SA_INTERRUPT,
  33.226 +						 "xenoprof",
  33.227 +						 NULL);
  33.228 +
  33.229 +		if (result < 0) {
  33.230 +			unbind_virq();
  33.231 +			return result;
  33.232 +		}
  33.233 +
  33.234 +		ovf_irq[i] = result;
  33.235 +	}
  33.236 +		
  33.237 +	return 0;
  33.238 +}
  33.239 +
  33.240 +
  33.241 +static void unmap_passive_list(void)
  33.242 +{
  33.243 +	int i;
  33.244 +	for (i = 0; i < pdomains; i++)
  33.245 +		xenoprof_arch_unmap_shared_buffer(&p_shared_buffer[i]);
  33.246 +	pdomains = 0;
  33.247 +}
  33.248 +
  33.249 +
  33.250 +static int map_xenoprof_buffer(int max_samples)
  33.251 +{
  33.252 +	struct xenoprof_get_buffer get_buffer;
  33.253 +	struct xenoprof_buf *buf;
  33.254 +	int ret, i;
  33.255 +
  33.256 +	if ( shared_buffer.buffer )
  33.257 +		return 0;
  33.258 +
  33.259 +	get_buffer.max_samples = max_samples;
  33.260 +	ret = xenoprof_arch_map_shared_buffer(&get_buffer, &shared_buffer);
  33.261 +	if (ret)
  33.262 +		return ret;
  33.263 +	nbuf = get_buffer.nbuf;
  33.264 +
  33.265 +	for (i=0; i< nbuf; i++) {
  33.266 +		buf = (struct xenoprof_buf*) 
  33.267 +			&shared_buffer.buffer[i * get_buffer.bufsize];
  33.268 +		BUG_ON(buf->vcpu_id >= MAX_VIRT_CPUS);
  33.269 +		xenoprof_buf[buf->vcpu_id] = buf;
  33.270 +	}
  33.271 +
  33.272 +	return 0;
  33.273 +}
  33.274 +
  33.275 +
  33.276 +static int xenoprof_setup(void)
  33.277 +{
  33.278 +	int ret;
  33.279 +
  33.280 +	if ( (ret = map_xenoprof_buffer(MAX_XENOPROF_SAMPLES)) )
  33.281 +		return ret;
  33.282 +
  33.283 +	if ( (ret = bind_virq()) )
  33.284 +		return ret;
  33.285 +
  33.286 +	if (xenoprof_is_primary) {
  33.287 +		/* Define dom0 as an active domain if not done yet */
  33.288 +		if (!active_defined) {
  33.289 +			domid_t domid;
  33.290 +			ret = HYPERVISOR_xenoprof_op(XENOPROF_reset_active_list, NULL);
  33.291 +			if (ret)
  33.292 +				goto err;
  33.293 +			domid = 0;
  33.294 +			ret = HYPERVISOR_xenoprof_op(XENOPROF_set_active, &domid);
  33.295 +			if (ret)
  33.296 +				goto err;
  33.297 +			active_defined = 1;
  33.298 +		}
  33.299 +
  33.300 +		ret = HYPERVISOR_xenoprof_op(XENOPROF_reserve_counters, NULL);
  33.301 +		if (ret)
  33.302 +			goto err;
  33.303 +		xenoprof_arch_counter();
  33.304 +		ret = HYPERVISOR_xenoprof_op(XENOPROF_setup_events, NULL);
  33.305 +
  33.306 +		if (ret)
  33.307 +			goto err;
  33.308 +	}
  33.309 +
  33.310 +	ret = HYPERVISOR_xenoprof_op(XENOPROF_enable_virq, NULL);
  33.311 +	if (ret)
  33.312 +		goto err;
  33.313 +
  33.314 +	xenoprof_enabled = 1;
  33.315 +	return 0;
  33.316 + err:
  33.317 +	unbind_virq();
  33.318 +	return ret;
  33.319 +}
  33.320 +
  33.321 +
  33.322 +static void xenoprof_shutdown(void)
  33.323 +{
  33.324 +	xenoprof_enabled = 0;
  33.325 +
  33.326 +	HYPERVISOR_xenoprof_op(XENOPROF_disable_virq, NULL);
  33.327 +
  33.328 +	if (xenoprof_is_primary) {
  33.329 +		HYPERVISOR_xenoprof_op(XENOPROF_release_counters, NULL);
  33.330 +		active_defined = 0;
  33.331 +	}
  33.332 +
  33.333 +	unbind_virq();
  33.334 +
  33.335 +	xenoprof_arch_unmap_shared_buffer(&shared_buffer);
  33.336 +	if (xenoprof_is_primary)
  33.337 +		unmap_passive_list();
  33.338 +}
  33.339 +
  33.340 +
  33.341 +static int xenoprof_start(void)
  33.342 +{
  33.343 +	int ret = 0;
  33.344 +
  33.345 +	if (xenoprof_is_primary)
  33.346 +		ret = HYPERVISOR_xenoprof_op(XENOPROF_start, NULL);
  33.347 +	if (!ret)
  33.348 +		xenoprof_arch_start();
  33.349 +	return ret;
  33.350 +}
  33.351 +
  33.352 +
  33.353 +static void xenoprof_stop(void)
  33.354 +{
  33.355 +	if (xenoprof_is_primary)
  33.356 +		HYPERVISOR_xenoprof_op(XENOPROF_stop, NULL);
  33.357 +	xenoprof_arch_stop();
  33.358 +}
  33.359 +
  33.360 +
  33.361 +static int xenoprof_set_active(int * active_domains,
  33.362 +			       unsigned int adomains)
  33.363 +{
  33.364 +	int ret = 0;
  33.365 +	int i;
  33.366 +	int set_dom0 = 0;
  33.367 +	domid_t domid;
  33.368 +
  33.369 +	if (!xenoprof_is_primary)
  33.370 +		return 0;
  33.371 +
  33.372 +	if (adomains > MAX_OPROF_DOMAINS)
  33.373 +		return -E2BIG;
  33.374 +
  33.375 +	ret = HYPERVISOR_xenoprof_op(XENOPROF_reset_active_list, NULL);
  33.376 +	if (ret)
  33.377 +		return ret;
  33.378 +
  33.379 +	for (i=0; i<adomains; i++) {
  33.380 +		domid = active_domains[i];
  33.381 +		if (domid != active_domains[i]) {
  33.382 +			ret = -EINVAL;
  33.383 +			goto out;
  33.384 +		}
  33.385 +		ret = HYPERVISOR_xenoprof_op(XENOPROF_set_active, &domid);
  33.386 +		if (ret)
  33.387 +			goto out;
  33.388 +		if (active_domains[i] == 0)
  33.389 +			set_dom0 = 1;
  33.390 +	}
  33.391 +	/* dom0 must always be active but may not be in the list */ 
  33.392 +	if (!set_dom0) {
  33.393 +		domid = 0;
  33.394 +		ret = HYPERVISOR_xenoprof_op(XENOPROF_set_active, &domid);
  33.395 +	}
  33.396 +
  33.397 +out:
  33.398 +	if (ret)
  33.399 +		HYPERVISOR_xenoprof_op(XENOPROF_reset_active_list, NULL);
  33.400 +	active_defined = !ret;
  33.401 +	return ret;
  33.402 +}
  33.403 +
  33.404 +static int xenoprof_set_passive(int * p_domains,
  33.405 +                                unsigned int pdoms)
  33.406 +{
  33.407 +	int ret;
  33.408 +	int i, j;
  33.409 +	struct xenoprof_buf *buf;
  33.410 +
  33.411 +	if (!xenoprof_is_primary)
  33.412 +        	return 0;
  33.413 +
  33.414 +	if (pdoms > MAX_OPROF_DOMAINS)
  33.415 +		return -E2BIG;
  33.416 +
  33.417 +	ret = HYPERVISOR_xenoprof_op(XENOPROF_reset_passive_list, NULL);
  33.418 +	if (ret)
  33.419 +		return ret;
  33.420 +	unmap_passive_list();
  33.421 +
  33.422 +	for (i = 0; i < pdoms; i++) {
  33.423 +		passive_domains[i].domain_id = p_domains[i];
  33.424 +		passive_domains[i].max_samples = 2048;
  33.425 +		ret = xenoprof_arch_set_passive(&passive_domains[i],
  33.426 +						&p_shared_buffer[i]);
  33.427 +		if (ret)
  33.428 +			goto out;
  33.429 +		for (j = 0; j < passive_domains[i].nbuf; j++) {
  33.430 +			buf = (struct xenoprof_buf *)
  33.431 +				&p_shared_buffer[i].buffer[j * passive_domains[i].bufsize];
  33.432 +			BUG_ON(buf->vcpu_id >= MAX_VIRT_CPUS);
  33.433 +			p_xenoprof_buf[i][buf->vcpu_id] = buf;
  33.434 +		}
  33.435 +	}
  33.436 +
  33.437 +	pdomains = pdoms;
  33.438 +	return 0;
  33.439 +
  33.440 +out:
  33.441 +	for (j = 0; j < i; j++)
  33.442 +		xenoprof_arch_unmap_shared_buffer(&p_shared_buffer[i]);
  33.443 +
  33.444 + 	return ret;
  33.445 +}
  33.446 +
  33.447 +struct oprofile_operations xenoprof_ops = {
  33.448 +#ifdef HAVE_XENOPROF_CREATE_FILES
  33.449 +	.create_files 	= xenoprof_create_files,
  33.450 +#endif
  33.451 +	.set_active	= xenoprof_set_active,
  33.452 +	.set_passive    = xenoprof_set_passive,
  33.453 +	.setup 		= xenoprof_setup,
  33.454 +	.shutdown	= xenoprof_shutdown,
  33.455 +	.start		= xenoprof_start,
  33.456 +	.stop		= xenoprof_stop
  33.457 +};
  33.458 +
  33.459 +
  33.460 +/* in order to get driverfs right */
  33.461 +static int using_xenoprof;
  33.462 +
  33.463 +int __init xenoprofile_init(struct oprofile_operations * ops)
  33.464 +{
  33.465 +	struct xenoprof_init init;
  33.466 +	int ret, i;
  33.467 +
  33.468 +	ret = HYPERVISOR_xenoprof_op(XENOPROF_init, &init);
  33.469 +	if (!ret) {
  33.470 +		xenoprof_arch_init_counter(&init);
  33.471 +		xenoprof_is_primary = init.is_primary;
  33.472 +
  33.473 +		/*  cpu_type is detected by Xen */
  33.474 +		cpu_type[XENOPROF_CPU_TYPE_SIZE-1] = 0;
  33.475 +		strncpy(cpu_type, init.cpu_type, XENOPROF_CPU_TYPE_SIZE - 1);
  33.476 +		xenoprof_ops.cpu_type = cpu_type;
  33.477 +
  33.478 +		init_driverfs();
  33.479 +		using_xenoprof = 1;
  33.480 +		*ops = xenoprof_ops;
  33.481 +
  33.482 +		for (i=0; i<NR_CPUS; i++)
  33.483 +			ovf_irq[i] = -1;
  33.484 +
  33.485 +		active_defined = 0;
  33.486 +	}
  33.487 +	printk(KERN_INFO "%s: ret %d, events %d, xenoprof_is_primary %d\n",
  33.488 +	       __func__, ret, init.num_events, xenoprof_is_primary);
  33.489 +	return ret;
  33.490 +}
  33.491 +
  33.492 +
  33.493 +void xenoprofile_exit(void)
  33.494 +{
  33.495 +	if (using_xenoprof)
  33.496 +		exit_driverfs();
  33.497 +
  33.498 +	xenoprof_arch_unmap_shared_buffer(&shared_buffer);
  33.499 +	if (xenoprof_is_primary) {
  33.500 +		unmap_passive_list();
  33.501 +		HYPERVISOR_xenoprof_op(XENOPROF_shutdown, NULL);
  33.502 +        }
  33.503 +}
    34.1 --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypervisor.h	Mon Nov 27 10:10:57 2006 -0700
    34.2 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypervisor.h	Tue Nov 28 10:37:36 2006 -0700
    34.3 @@ -98,7 +98,6 @@ void xen_pgd_pin(unsigned long ptr);
    34.4  void xen_pgd_unpin(unsigned long ptr);
    34.5  
    34.6  void xen_set_ldt(unsigned long ptr, unsigned long bytes);
    34.7 -void xen_machphys_update(unsigned long mfn, unsigned long pfn);
    34.8  
    34.9  #ifdef CONFIG_SMP
   34.10  #include <linux/cpumask.h>
    35.1 --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/io.h	Mon Nov 27 10:10:57 2006 -0700
    35.2 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/io.h	Tue Nov 28 10:37:36 2006 -0700
    35.3 @@ -54,7 +54,8 @@
    35.4   * Convert a physical pointer to a virtual kernel pointer for /dev/mem
    35.5   * access
    35.6   */
    35.7 -#define xlate_dev_mem_ptr(p)	__va(p)
    35.8 +#define xlate_dev_mem_ptr(p, sz)	ioremap(p, sz)
    35.9 +#define xlate_dev_mem_ptr_unmap(p)	iounmap(p)
   35.10  
   35.11  /*
   35.12   * Convert a virtual cached pointer to an uncached pointer
    36.1 --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/maddr.h	Mon Nov 27 10:10:57 2006 -0700
    36.2 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/maddr.h	Tue Nov 28 10:37:36 2006 -0700
    36.3 @@ -9,6 +9,15 @@
    36.4  #define FOREIGN_FRAME_BIT	(1UL<<31)
    36.5  #define FOREIGN_FRAME(m)	((m) | FOREIGN_FRAME_BIT)
    36.6  
    36.7 +/* Definitions for machine and pseudophysical addresses. */
    36.8 +#ifdef CONFIG_X86_PAE
    36.9 +typedef unsigned long long paddr_t;
   36.10 +typedef unsigned long long maddr_t;
   36.11 +#else
   36.12 +typedef unsigned long paddr_t;
   36.13 +typedef unsigned long maddr_t;
   36.14 +#endif
   36.15 +
   36.16  #ifdef CONFIG_XEN
   36.17  
   36.18  extern unsigned long *phys_to_machine_mapping;
   36.19 @@ -101,26 +110,6 @@ static inline void set_phys_to_machine(u
   36.20  	phys_to_machine_mapping[pfn] = mfn;
   36.21  }
   36.22  
   36.23 -
   36.24 -#else /* !CONFIG_XEN */
   36.25 -
   36.26 -#define pfn_to_mfn(pfn) (pfn)
   36.27 -#define mfn_to_pfn(mfn) (mfn)
   36.28 -#define mfn_to_local_pfn(mfn) (mfn)
   36.29 -#define set_phys_to_machine(pfn, mfn) BUG_ON((pfn) != (mfn))
   36.30 -#define phys_to_machine_mapping_valid(pfn) (1)
   36.31 -
   36.32 -#endif /* !CONFIG_XEN */
   36.33 -
   36.34 -/* Definitions for machine and pseudophysical addresses. */
   36.35 -#ifdef CONFIG_X86_PAE
   36.36 -typedef unsigned long long paddr_t;
   36.37 -typedef unsigned long long maddr_t;
   36.38 -#else
   36.39 -typedef unsigned long paddr_t;
   36.40 -typedef unsigned long maddr_t;
   36.41 -#endif
   36.42 -
   36.43  static inline maddr_t phys_to_machine(paddr_t phys)
   36.44  {
   36.45  	maddr_t machine = pfn_to_mfn(phys >> PAGE_SHIFT);
   36.46 @@ -148,6 +137,19 @@ static inline paddr_t pte_machine_to_phy
   36.47  	return phys;
   36.48  }
   36.49  
   36.50 +#else /* !CONFIG_XEN */
   36.51 +
   36.52 +#define pfn_to_mfn(pfn) (pfn)
   36.53 +#define mfn_to_pfn(mfn) (mfn)
   36.54 +#define mfn_to_local_pfn(mfn) (mfn)
   36.55 +#define set_phys_to_machine(pfn, mfn) BUG_ON((pfn) != (mfn))
   36.56 +#define phys_to_machine_mapping_valid(pfn) (1)
   36.57 +#define phys_to_machine(phys) ((maddr_t)(phys))
   36.58 +#define machine_to_phys(mach) ((paddr_t)(mach))
   36.59 +#define pte_machine_to_phys(mach) ((paddr_t)(mach))
   36.60 +
   36.61 +#endif /* !CONFIG_XEN */
   36.62 +
   36.63  /* VIRT <-> MACHINE conversion */
   36.64  #define virt_to_machine(v)	(phys_to_machine(__pa(v)))
   36.65  #define virt_to_mfn(v)		(pfn_to_mfn(__pa(v) >> PAGE_SHIFT))
    37.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    37.2 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/xenoprof.h	Tue Nov 28 10:37:36 2006 -0700
    37.3 @@ -0,0 +1,48 @@
    37.4 +/******************************************************************************
    37.5 + * asm-i386/mach-xen/asm/xenoprof.h
    37.6 + *
    37.7 + * Copyright (c) 2006 Isaku Yamahata <yamahata at valinux co jp>
    37.8 + *                    VA Linux Systems Japan K.K.
    37.9 + *
   37.10 + * This program is free software; you can redistribute it and/or modify
   37.11 + * it under the terms of the GNU General Public License as published by
   37.12 + * the Free Software Foundation; either version 2 of the License, or
   37.13 + * (at your option) any later version.
   37.14 + *
   37.15 + * This program is distributed in the hope that it will be useful,
   37.16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   37.17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   37.18 + * GNU General Public License for more details.
   37.19 + *
   37.20 + * You should have received a copy of the GNU General Public License
   37.21 + * along with this program; if not, write to the Free Software
   37.22 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   37.23 + *
   37.24 + */
   37.25 +#ifndef __ASM_XENOPROF_H__
   37.26 +#define __ASM_XENOPROF_H__
   37.27 +#ifdef CONFIG_XEN
   37.28 +
   37.29 +struct super_block;
   37.30 +struct dentry;
   37.31 +int xenoprof_create_files(struct super_block * sb, struct dentry * root);
   37.32 +#define HAVE_XENOPROF_CREATE_FILES
   37.33 +
   37.34 +struct xenoprof_init;
   37.35 +void xenoprof_arch_init_counter(struct xenoprof_init *init);
   37.36 +void xenoprof_arch_counter(void);
   37.37 +void xenoprof_arch_start(void);
   37.38 +void xenoprof_arch_stop(void);
   37.39 +
   37.40 +struct xenoprof_arch_shared_buffer {
   37.41 +	/* nothing */
   37.42 +};
   37.43 +struct xenoprof_shared_buffer;
   37.44 +void xenoprof_arch_unmap_shared_buffer(struct xenoprof_shared_buffer* sbuf);
   37.45 +struct xenoprof_get_buffer;
   37.46 +int xenoprof_arch_map_shared_buffer(struct xenoprof_get_buffer* get_buffer, struct xenoprof_shared_buffer* sbuf);
   37.47 +struct xenoprof_passive;
   37.48 +int xenoprof_arch_set_passive(struct xenoprof_passive* pdomain, struct xenoprof_shared_buffer* sbuf);
   37.49 +
   37.50 +#endif /* CONFIG_XEN */
   37.51 +#endif /* __ASM_XENOPROF_H__ */
    38.1 --- a/linux-2.6-xen-sparse/include/asm-ia64/maddr.h	Mon Nov 27 10:10:57 2006 -0700
    38.2 +++ b/linux-2.6-xen-sparse/include/asm-ia64/maddr.h	Tue Nov 28 10:37:36 2006 -0700
    38.3 @@ -96,11 +96,6 @@ mfn_to_local_pfn(unsigned long mfn)
    38.4  #define virt_to_machine(virt) __pa(virt) // for tpmfront.c
    38.5  
    38.6  #define set_phys_to_machine(pfn, mfn) do { } while (0)
    38.7 -#ifdef CONFIG_VMX_GUEST
    38.8 -extern void xen_machphys_update(unsigned long mfn, unsigned long pfn);
    38.9 -#else /* CONFIG_VMX_GUEST */
   38.10 -#define xen_machphys_update(mfn, pfn) do { } while (0)
   38.11 -#endif /* CONFIG_VMX_GUEST */
   38.12  
   38.13  typedef unsigned long maddr_t;	// to compile netback, netfront
   38.14  
    39.1 --- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/io.h	Mon Nov 27 10:10:57 2006 -0700
    39.2 +++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/io.h	Tue Nov 28 10:37:36 2006 -0700
    39.3 @@ -346,7 +346,8 @@ extern int iommu_bio_merge;
    39.4   * Convert a physical pointer to a virtual kernel pointer for /dev/mem
    39.5   * access
    39.6   */
    39.7 -#define xlate_dev_mem_ptr(p)	__va(p)
    39.8 +#define xlate_dev_mem_ptr(p, sz)	ioremap(p, sz)
    39.9 +#define xlate_dev_mem_ptr_unmap(p)	iounmap(p)
   39.10  
   39.11  /*
   39.12   * Convert a virtual cached pointer to an uncached pointer
    40.1 --- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/maddr.h	Mon Nov 27 10:10:57 2006 -0700
    40.2 +++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/maddr.h	Tue Nov 28 10:37:36 2006 -0700
    40.3 @@ -9,6 +9,10 @@
    40.4  #define FOREIGN_FRAME_BIT	(1UL<<63)
    40.5  #define FOREIGN_FRAME(m)	((m) | FOREIGN_FRAME_BIT)
    40.6  
    40.7 +/* Definitions for machine and pseudophysical addresses. */
    40.8 +typedef unsigned long paddr_t;
    40.9 +typedef unsigned long maddr_t;
   40.10 +
   40.11  #ifdef CONFIG_XEN
   40.12  
   40.13  extern unsigned long *phys_to_machine_mapping;
   40.14 @@ -99,20 +103,6 @@ static inline void set_phys_to_machine(u
   40.15  	phys_to_machine_mapping[pfn] = mfn;
   40.16  }
   40.17  
   40.18 -#else /* !CONFIG_XEN */
   40.19 -
   40.20 -#define pfn_to_mfn(pfn) (pfn)
   40.21 -#define mfn_to_pfn(mfn) (mfn)
   40.22 -#define mfn_to_local_pfn(mfn) (mfn)
   40.23 -#define set_phys_to_machine(pfn, mfn) BUG_ON((pfn) != (mfn))
   40.24 -#define phys_to_machine_mapping_valid(pfn) (1)
   40.25 -
   40.26 -#endif /* !CONFIG_XEN */
   40.27 -
   40.28 -/* Definitions for machine and pseudophysical addresses. */
   40.29 -typedef unsigned long paddr_t;
   40.30 -typedef unsigned long maddr_t;
   40.31 -
   40.32  static inline maddr_t phys_to_machine(paddr_t phys)
   40.33  {
   40.34  	maddr_t machine = pfn_to_mfn(phys >> PAGE_SHIFT);
   40.35 @@ -135,6 +125,19 @@ static inline paddr_t pte_machine_to_phy
   40.36  	return phys;
   40.37  }
   40.38  
   40.39 +#else /* !CONFIG_XEN */
   40.40 +
   40.41 +#define pfn_to_mfn(pfn) (pfn)
   40.42 +#define mfn_to_pfn(mfn) (mfn)
   40.43 +#define mfn_to_local_pfn(mfn) (mfn)
   40.44 +#define set_phys_to_machine(pfn, mfn) BUG_ON((pfn) != (mfn))
   40.45 +#define phys_to_machine_mapping_valid(pfn) (1)
   40.46 +#define phys_to_machine(phys) ((maddr_t)(phys))
   40.47 +#define machine_to_phys(mach) ((paddr_t)(mach))
   40.48 +#define pte_machine_to_phys(mach) ((paddr_t)(mach))
   40.49 +
   40.50 +#endif /* !CONFIG_XEN */
   40.51 +
   40.52  /* VIRT <-> MACHINE conversion */
   40.53  #define virt_to_machine(v)	(phys_to_machine(__pa(v)))
   40.54  #define virt_to_mfn(v)		(pfn_to_mfn(__pa(v) >> PAGE_SHIFT))
    41.1 --- a/linux-2.6-xen-sparse/include/linux/skbuff.h	Mon Nov 27 10:10:57 2006 -0700
    41.2 +++ b/linux-2.6-xen-sparse/include/linux/skbuff.h	Tue Nov 28 10:37:36 2006 -0700
    41.3 @@ -974,15 +974,16 @@ static inline void skb_reserve(struct sk
    41.4  #define NET_IP_ALIGN	2
    41.5  #endif
    41.6  
    41.7 -extern int ___pskb_trim(struct sk_buff *skb, unsigned int len, int realloc);
    41.8 +extern int ___pskb_trim(struct sk_buff *skb, unsigned int len);
    41.9  
   41.10  static inline void __skb_trim(struct sk_buff *skb, unsigned int len)
   41.11  {
   41.12 -	if (!skb->data_len) {
   41.13 -		skb->len  = len;
   41.14 -		skb->tail = skb->data + len;
   41.15 -	} else
   41.16 -		___pskb_trim(skb, len, 0);
   41.17 +	if (unlikely(skb->data_len)) {
   41.18 +		WARN_ON(1);
   41.19 +		return;
   41.20 +	}
   41.21 +	skb->len  = len;
   41.22 +	skb->tail = skb->data + len;
   41.23  }
   41.24  
   41.25  /**
   41.26 @@ -992,6 +993,7 @@ static inline void __skb_trim(struct sk_
   41.27   *
   41.28   *	Cut the length of a buffer down by removing data from the tail. If
   41.29   *	the buffer is already under the length specified it is not modified.
   41.30 + *	The skb must be linear.
   41.31   */
   41.32  static inline void skb_trim(struct sk_buff *skb, unsigned int len)
   41.33  {
   41.34 @@ -1002,12 +1004,10 @@ static inline void skb_trim(struct sk_bu
   41.35  
   41.36  static inline int __pskb_trim(struct sk_buff *skb, unsigned int len)
   41.37  {
   41.38 -	if (!skb->data_len) {
   41.39 -		skb->len  = len;
   41.40 -		skb->tail = skb->data+len;
   41.41 -		return 0;
   41.42 -	}
   41.43 -	return ___pskb_trim(skb, len, 1);
   41.44 +	if (skb->data_len)
   41.45 +		return ___pskb_trim(skb, len);
   41.46 +	__skb_trim(skb, len);
   41.47 +	return 0;
   41.48  }
   41.49  
   41.50  static inline int pskb_trim(struct sk_buff *skb, unsigned int len)
    42.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    42.2 +++ b/linux-2.6-xen-sparse/include/xen/xenoprof.h	Tue Nov 28 10:37:36 2006 -0700
    42.3 @@ -0,0 +1,42 @@
    42.4 +/******************************************************************************
    42.5 + * xen/xenoprof.h
    42.6 + *
    42.7 + * Copyright (c) 2006 Isaku Yamahata <yamahata at valinux co jp>
    42.8 + *                    VA Linux Systems Japan K.K.
    42.9 + *
   42.10 + * This program is free software; you can redistribute it and/or modify
   42.11 + * it under the terms of the GNU General Public License as published by
   42.12 + * the Free Software Foundation; either version 2 of the License, or
   42.13 + * (at your option) any later version.
   42.14 + *
   42.15 + * This program is distributed in the hope that it will be useful,
   42.16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   42.17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   42.18 + * GNU General Public License for more details.
   42.19 + *
   42.20 + * You should have received a copy of the GNU General Public License
   42.21 + * along with this program; if not, write to the Free Software
   42.22 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   42.23 + *
   42.24 + */
   42.25 +
   42.26 +#ifndef __XEN_XENOPROF_H__
   42.27 +#define __XEN_XENOPROF_H__
   42.28 +#ifdef CONFIG_XEN
   42.29 +
   42.30 +#include <asm/xenoprof.h>
   42.31 +
   42.32 +struct oprofile_operations;
   42.33 +int xenoprofile_init(struct oprofile_operations * ops);
   42.34 +void xenoprofile_exit(void);
   42.35 +
   42.36 +struct xenoprof_shared_buffer {
   42.37 +	char					*buffer;
   42.38 +	struct xenoprof_arch_shared_buffer	arch;
   42.39 +};
   42.40 +#else
   42.41 +#define xenoprofile_init(ops)	(-ENOSYS)
   42.42 +#define xenoprofile_exit()	do { } while (0)
   42.43 +
   42.44 +#endif /* CONFIG_XEN */
   42.45 +#endif /* __XEN_XENOPROF_H__ */
    43.1 --- a/linux-2.6-xen-sparse/mm/memory.c	Mon Nov 27 10:10:57 2006 -0700
    43.2 +++ b/linux-2.6-xen-sparse/mm/memory.c	Tue Nov 28 10:37:36 2006 -0700
    43.3 @@ -1535,6 +1535,7 @@ static inline void cow_user_page(struct 
    43.4  		if (__copy_from_user_inatomic(kaddr, uaddr, PAGE_SIZE))
    43.5  			memset(kaddr, 0, PAGE_SIZE);
    43.6  		kunmap_atomic(kaddr, KM_USER0);
    43.7 +		flush_dcache_page(dst);
    43.8  		return;
    43.9  		
   43.10  	}
    44.1 --- a/linux-2.6-xen-sparse/mm/mmap.c	Mon Nov 27 10:10:57 2006 -0700
    44.2 +++ b/linux-2.6-xen-sparse/mm/mmap.c	Tue Nov 28 10:37:36 2006 -0700
    44.3 @@ -30,6 +30,10 @@
    44.4  #include <asm/cacheflush.h>
    44.5  #include <asm/tlb.h>
    44.6  
    44.7 +#ifndef arch_mmap_check
    44.8 +#define arch_mmap_check(addr, len, flags)	(0)
    44.9 +#endif
   44.10 +
   44.11  static void unmap_region(struct mm_struct *mm,
   44.12  		struct vm_area_struct *vma, struct vm_area_struct *prev,
   44.13  		unsigned long start, unsigned long end);
   44.14 @@ -906,6 +910,10 @@ unsigned long do_mmap_pgoff(struct file 
   44.15  	if (!len)
   44.16  		return -EINVAL;
   44.17  
   44.18 +	error = arch_mmap_check(addr, len, flags);
   44.19 +	if (error)
   44.20 +		return error;
   44.21 +
   44.22  	/* Careful about overflows.. */
   44.23  	len = PAGE_ALIGN(len);
   44.24  	if (!len || len > TASK_SIZE)
   44.25 @@ -1846,6 +1854,7 @@ unsigned long do_brk(unsigned long addr,
   44.26  	unsigned long flags;
   44.27  	struct rb_node ** rb_link, * rb_parent;
   44.28  	pgoff_t pgoff = addr >> PAGE_SHIFT;
   44.29 +	int error;
   44.30  
   44.31  	len = PAGE_ALIGN(len);
   44.32  	if (!len)
   44.33 @@ -1854,6 +1863,12 @@ unsigned long do_brk(unsigned long addr,
   44.34  	if ((addr + len) > TASK_SIZE || (addr + len) < addr)
   44.35  		return -EINVAL;
   44.36  
   44.37 +	flags = VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT | mm->def_flags;
   44.38 +
   44.39 +	error = arch_mmap_check(addr, len, flags);
   44.40 +	if (error)
   44.41 +		return error;
   44.42 +
   44.43  	/*
   44.44  	 * mlock MCL_FUTURE?
   44.45  	 */
   44.46 @@ -1894,8 +1909,6 @@ unsigned long do_brk(unsigned long addr,
   44.47  	if (security_vm_enough_memory(len >> PAGE_SHIFT))
   44.48  		return -ENOMEM;
   44.49  
   44.50 -	flags = VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT | mm->def_flags;
   44.51 -
   44.52  	/* Can we just expand an old private anonymous mapping? */
   44.53  	if (vma_merge(mm, prev, addr, addr + len, flags,
   44.54  					NULL, NULL, pgoff, NULL))
    45.1 --- a/linux-2.6-xen-sparse/net/core/skbuff.c	Mon Nov 27 10:10:57 2006 -0700
    45.2 +++ b/linux-2.6-xen-sparse/net/core/skbuff.c	Tue Nov 28 10:37:36 2006 -0700
    45.3 @@ -261,11 +261,11 @@ nodata:
    45.4  }
    45.5  
    45.6  
    45.7 -static void skb_drop_fraglist(struct sk_buff *skb)
    45.8 +static void skb_drop_list(struct sk_buff **listp)
    45.9  {
   45.10 -	struct sk_buff *list = skb_shinfo(skb)->frag_list;
   45.11 +	struct sk_buff *list = *listp;
   45.12  
   45.13 -	skb_shinfo(skb)->frag_list = NULL;
   45.14 +	*listp = NULL;
   45.15  
   45.16  	do {
   45.17  		struct sk_buff *this = list;
   45.18 @@ -274,6 +274,11 @@ static void skb_drop_fraglist(struct sk_
   45.19  	} while (list);
   45.20  }
   45.21  
   45.22 +static inline void skb_drop_fraglist(struct sk_buff *skb)
   45.23 +{
   45.24 +	skb_drop_list(&skb_shinfo(skb)->frag_list);
   45.25 +}
   45.26 +
   45.27  static void skb_clone_fraglist(struct sk_buff *skb)
   45.28  {
   45.29  	struct sk_buff *list;
   45.30 @@ -604,6 +609,7 @@ struct sk_buff *pskb_copy(struct sk_buff
   45.31  	n->csum	     = skb->csum;
   45.32  	n->ip_summed = skb->ip_summed;
   45.33  
   45.34 +	n->truesize += skb->data_len;
   45.35  	n->data_len  = skb->data_len;
   45.36  	n->len	     = skb->len;
   45.37  
   45.38 @@ -798,49 +804,86 @@ struct sk_buff *skb_pad(struct sk_buff *
   45.39  	return nskb;
   45.40  }	
   45.41   
   45.42 -/* Trims skb to length len. It can change skb pointers, if "realloc" is 1.
   45.43 - * If realloc==0 and trimming is impossible without change of data,
   45.44 - * it is BUG().
   45.45 +/* Trims skb to length len. It can change skb pointers.
   45.46   */
   45.47  
   45.48 -int ___pskb_trim(struct sk_buff *skb, unsigned int len, int realloc)
   45.49 +int ___pskb_trim(struct sk_buff *skb, unsigned int len)
   45.50  {
   45.51 +	struct sk_buff **fragp;
   45.52 +	struct sk_buff *frag;
   45.53  	int offset = skb_headlen(skb);
   45.54  	int nfrags = skb_shinfo(skb)->nr_frags;
   45.55  	int i;
   45.56 +	int err;
   45.57  
   45.58 -	for (i = 0; i < nfrags; i++) {
   45.59 +	if (skb_cloned(skb) &&
   45.60 +	    unlikely((err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC))))
   45.61 +		return err;
   45.62 +
   45.63 +	i = 0;
   45.64 +	if (offset >= len)
   45.65 +		goto drop_pages;
   45.66 +
   45.67 +	for (; i < nfrags; i++) {
   45.68  		int end = offset + skb_shinfo(skb)->frags[i].size;
   45.69 -		if (end > len) {
   45.70 -			if (skb_cloned(skb)) {
   45.71 -				BUG_ON(!realloc);
   45.72 -				if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
   45.73 -					return -ENOMEM;
   45.74 -			}
   45.75 -			if (len <= offset) {
   45.76 -				put_page(skb_shinfo(skb)->frags[i].page);
   45.77 -				skb_shinfo(skb)->nr_frags--;
   45.78 -			} else {
   45.79 -				skb_shinfo(skb)->frags[i].size = len - offset;
   45.80 -			}
   45.81 +
   45.82 +		if (end < len) {
   45.83 +			offset = end;
   45.84 +			continue;
   45.85  		}
   45.86 -		offset = end;
   45.87 +
   45.88 +		skb_shinfo(skb)->frags[i++].size = len - offset;
   45.89 +
   45.90 +drop_pages:
   45.91 +		skb_shinfo(skb)->nr_frags = i;
   45.92 +
   45.93 +		for (; i < nfrags; i++)
   45.94 +			put_page(skb_shinfo(skb)->frags[i].page);
   45.95 +
   45.96 +		if (skb_shinfo(skb)->frag_list)
   45.97 +			skb_drop_fraglist(skb);
   45.98 +		goto done;
   45.99  	}
  45.100  
  45.101 -	if (offset < len) {
  45.102 +	for (fragp = &skb_shinfo(skb)->frag_list; (frag = *fragp);
  45.103 +	     fragp = &frag->next) {
  45.104 +		int end = offset + frag->len;
  45.105 +
  45.106 +		if (skb_shared(frag)) {
  45.107 +			struct sk_buff *nfrag;
  45.108 +
  45.109 +			nfrag = skb_clone(frag, GFP_ATOMIC);
  45.110 +			if (unlikely(!nfrag))
  45.111 +				return -ENOMEM;
  45.112 +
  45.113 +			nfrag->next = frag->next;
  45.114 +			kfree_skb(frag);
  45.115 +			frag = nfrag;
  45.116 +			*fragp = frag;
  45.117 +		}
  45.118 +
  45.119 +		if (end < len) {
  45.120 +			offset = end;
  45.121 +			continue;
  45.122 +		}
  45.123 +
  45.124 +		if (end > len &&
  45.125 +		    unlikely((err = pskb_trim(frag, len - offset))))
  45.126 +			return err;
  45.127 +
  45.128 +		if (frag->next)
  45.129 +			skb_drop_list(&frag->next);
  45.130 +		break;
  45.131 +	}
  45.132 +
  45.133 +done:
  45.134 +	if (len > skb_headlen(skb)) {
  45.135  		skb->data_len -= skb->len - len;
  45.136  		skb->len       = len;
  45.137  	} else {
  45.138 -		if (len <= skb_headlen(skb)) {
  45.139 -			skb->len      = len;
  45.140 -			skb->data_len = 0;
  45.141 -			skb->tail     = skb->data + len;
  45.142 -			if (skb_shinfo(skb)->frag_list && !skb_cloned(skb))
  45.143 -				skb_drop_fraglist(skb);
  45.144 -		} else {
  45.145 -			skb->data_len -= skb->len - len;
  45.146 -			skb->len       = len;
  45.147 -		}
  45.148 +		skb->len       = len;
  45.149 +		skb->data_len  = 0;
  45.150 +		skb->tail      = skb->data + len;
  45.151  	}
  45.152  
  45.153  	return 0;
    46.1 --- a/patches/linux-2.6.16.29/blktap-aio-16_03_06.patch	Mon Nov 27 10:10:57 2006 -0700
    46.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    46.3 @@ -1,294 +0,0 @@
    46.4 -diff -pruN ../orig-linux-2.6.16.29/fs/aio.c ./fs/aio.c
    46.5 ---- ../orig-linux-2.6.16.29/fs/aio.c	2006-09-12 19:02:10.000000000 +0100
    46.6 -+++ ./fs/aio.c	2006-09-19 13:58:49.000000000 +0100
    46.7 -@@ -34,6 +34,11 @@
    46.8 - #include <asm/uaccess.h>
    46.9 - #include <asm/mmu_context.h>
   46.10 - 
   46.11 -+#ifdef CONFIG_EPOLL
   46.12 -+#include <linux/poll.h>
   46.13 -+#include <linux/eventpoll.h>
   46.14 -+#endif
   46.15 -+
   46.16 - #if DEBUG > 1
   46.17 - #define dprintk		printk
   46.18 - #else
   46.19 -@@ -1016,6 +1021,10 @@ put_rq:
   46.20 - 	if (waitqueue_active(&ctx->wait))
   46.21 - 		wake_up(&ctx->wait);
   46.22 - 
   46.23 -+#ifdef CONFIG_EPOLL
   46.24 -+	if (ctx->file && waitqueue_active(&ctx->poll_wait))
   46.25 -+		wake_up(&ctx->poll_wait);
   46.26 -+#endif
   46.27 - 	if (ret)
   46.28 - 		put_ioctx(ctx);
   46.29 - 
   46.30 -@@ -1025,6 +1034,8 @@ put_rq:
   46.31 - /* aio_read_evt
   46.32 -  *	Pull an event off of the ioctx's event ring.  Returns the number of 
   46.33 -  *	events fetched (0 or 1 ;-)
   46.34 -+ *	If ent parameter is 0, just returns the number of events that would
   46.35 -+ *	be fetched.
   46.36 -  *	FIXME: make this use cmpxchg.
   46.37 -  *	TODO: make the ringbuffer user mmap()able (requires FIXME).
   46.38 -  */
   46.39 -@@ -1047,13 +1058,18 @@ static int aio_read_evt(struct kioctx *i
   46.40 - 
   46.41 - 	head = ring->head % info->nr;
   46.42 - 	if (head != ring->tail) {
   46.43 --		struct io_event *evp = aio_ring_event(info, head, KM_USER1);
   46.44 --		*ent = *evp;
   46.45 --		head = (head + 1) % info->nr;
   46.46 --		smp_mb(); /* finish reading the event before updatng the head */
   46.47 --		ring->head = head;
   46.48 --		ret = 1;
   46.49 --		put_aio_ring_event(evp, KM_USER1);
   46.50 -+		if (ent) { /* event requested */
   46.51 -+			struct io_event *evp =
   46.52 -+				aio_ring_event(info, head, KM_USER1);
   46.53 -+			*ent = *evp;
   46.54 -+			head = (head + 1) % info->nr;
   46.55 -+			/* finish reading the event before updatng the head */
   46.56 -+			smp_mb();
   46.57 -+			ring->head = head;
   46.58 -+			ret = 1;
   46.59 -+			put_aio_ring_event(evp, KM_USER1);
   46.60 -+		} else /* only need to know availability */
   46.61 -+			ret = 1;
   46.62 - 	}
   46.63 - 	spin_unlock(&info->ring_lock);
   46.64 - 
   46.65 -@@ -1236,9 +1252,78 @@ static void io_destroy(struct kioctx *io
   46.66 - 
   46.67 - 	aio_cancel_all(ioctx);
   46.68 - 	wait_for_all_aios(ioctx);
   46.69 -+#ifdef CONFIG_EPOLL
   46.70 -+	/* forget the poll file, but it's up to the user to close it */
   46.71 -+	if (ioctx->file) {
   46.72 -+		ioctx->file->private_data = 0;
   46.73 -+		ioctx->file = 0;
   46.74 -+	}
   46.75 -+#endif
   46.76 - 	put_ioctx(ioctx);	/* once for the lookup */
   46.77 - }
   46.78 - 
   46.79 -+#ifdef CONFIG_EPOLL
   46.80 -+
   46.81 -+static int aio_queue_fd_close(struct inode *inode, struct file *file)
   46.82 -+{
   46.83 -+	struct kioctx *ioctx = file->private_data;
   46.84 -+	if (ioctx) {
   46.85 -+		file->private_data = 0;
   46.86 -+		spin_lock_irq(&ioctx->ctx_lock);
   46.87 -+		ioctx->file = 0;
   46.88 -+		spin_unlock_irq(&ioctx->ctx_lock);
   46.89 -+	}
   46.90 -+	return 0;
   46.91 -+}
   46.92 -+
   46.93 -+static unsigned int aio_queue_fd_poll(struct file *file, poll_table *wait)
   46.94 -+{	unsigned int pollflags = 0;
   46.95 -+	struct kioctx *ioctx = file->private_data;
   46.96 -+
   46.97 -+	if (ioctx) {
   46.98 -+
   46.99 -+		spin_lock_irq(&ioctx->ctx_lock);
  46.100 -+		/* Insert inside our poll wait queue */
  46.101 -+		poll_wait(file, &ioctx->poll_wait, wait);
  46.102 -+
  46.103 -+		/* Check our condition */
  46.104 -+		if (aio_read_evt(ioctx, 0))
  46.105 -+			pollflags = POLLIN | POLLRDNORM;
  46.106 -+		spin_unlock_irq(&ioctx->ctx_lock);
  46.107 -+	}
  46.108 -+
  46.109 -+	return pollflags;
  46.110 -+}
  46.111 -+
  46.112 -+static struct file_operations aioq_fops = {
  46.113 -+	.release	= aio_queue_fd_close,
  46.114 -+	.poll		= aio_queue_fd_poll
  46.115 -+};
  46.116 -+
  46.117 -+/* make_aio_fd:
  46.118 -+ *  Create a file descriptor that can be used to poll the event queue.
  46.119 -+ *  Based and piggybacked on the excellent epoll code.
  46.120 -+ */
  46.121 -+
  46.122 -+static int make_aio_fd(struct kioctx *ioctx)
  46.123 -+{
  46.124 -+	int error, fd;
  46.125 -+	struct inode *inode;
  46.126 -+	struct file *file;
  46.127 -+
  46.128 -+	error = ep_getfd(&fd, &inode, &file, NULL, &aioq_fops);
  46.129 -+	if (error)
  46.130 -+		return error;
  46.131 -+
  46.132 -+	/* associate the file with the IO context */
  46.133 -+	file->private_data = ioctx;
  46.134 -+	ioctx->file = file;
  46.135 -+	init_waitqueue_head(&ioctx->poll_wait);
  46.136 -+	return fd;
  46.137 -+}
  46.138 -+#endif
  46.139 -+
  46.140 -+
  46.141 - /* sys_io_setup:
  46.142 -  *	Create an aio_context capable of receiving at least nr_events.
  46.143 -  *	ctxp must not point to an aio_context that already exists, and
  46.144 -@@ -1251,18 +1336,30 @@ static void io_destroy(struct kioctx *io
  46.145 -  *	resources are available.  May fail with -EFAULT if an invalid
  46.146 -  *	pointer is passed for ctxp.  Will fail with -ENOSYS if not
  46.147 -  *	implemented.
  46.148 -+ *
  46.149 -+ *	To request a selectable fd, the user context has to be initialized
  46.150 -+ *	to 1, instead of 0, and the return value is the fd.
  46.151 -+ *	This keeps the system call compatible, since a non-zero value
  46.152 -+ *	was not allowed so far.
  46.153 -  */
  46.154 - asmlinkage long sys_io_setup(unsigned nr_events, aio_context_t __user *ctxp)
  46.155 - {
  46.156 - 	struct kioctx *ioctx = NULL;
  46.157 - 	unsigned long ctx;
  46.158 - 	long ret;
  46.159 -+	int make_fd = 0;
  46.160 - 
  46.161 - 	ret = get_user(ctx, ctxp);
  46.162 - 	if (unlikely(ret))
  46.163 - 		goto out;
  46.164 - 
  46.165 - 	ret = -EINVAL;
  46.166 -+#ifdef CONFIG_EPOLL
  46.167 -+	if (ctx == 1) {
  46.168 -+		make_fd = 1;
  46.169 -+		ctx = 0;
  46.170 -+	}
  46.171 -+#endif
  46.172 - 	if (unlikely(ctx || nr_events == 0)) {
  46.173 - 		pr_debug("EINVAL: io_setup: ctx %lu nr_events %u\n",
  46.174 - 		         ctx, nr_events);
  46.175 -@@ -1273,8 +1370,12 @@ asmlinkage long sys_io_setup(unsigned nr
  46.176 - 	ret = PTR_ERR(ioctx);
  46.177 - 	if (!IS_ERR(ioctx)) {
  46.178 - 		ret = put_user(ioctx->user_id, ctxp);
  46.179 --		if (!ret)
  46.180 --			return 0;
  46.181 -+#ifdef CONFIG_EPOLL
  46.182 -+		if (make_fd && ret >= 0)
  46.183 -+			ret = make_aio_fd(ioctx);
  46.184 -+#endif
  46.185 -+		if (ret >= 0)
  46.186 -+			return ret;
  46.187 - 
  46.188 - 		get_ioctx(ioctx); /* io_destroy() expects us to hold a ref */
  46.189 - 		io_destroy(ioctx);
  46.190 -diff -pruN ../orig-linux-2.6.16.29/fs/eventpoll.c ./fs/eventpoll.c
  46.191 ---- ../orig-linux-2.6.16.29/fs/eventpoll.c	2006-09-12 19:02:10.000000000 +0100
  46.192 -+++ ./fs/eventpoll.c	2006-09-19 13:58:49.000000000 +0100
  46.193 -@@ -235,8 +235,6 @@ struct ep_pqueue {
  46.194 - 
  46.195 - static void ep_poll_safewake_init(struct poll_safewake *psw);
  46.196 - static void ep_poll_safewake(struct poll_safewake *psw, wait_queue_head_t *wq);
  46.197 --static int ep_getfd(int *efd, struct inode **einode, struct file **efile,
  46.198 --		    struct eventpoll *ep);
  46.199 - static int ep_alloc(struct eventpoll **pep);
  46.200 - static void ep_free(struct eventpoll *ep);
  46.201 - static struct epitem *ep_find(struct eventpoll *ep, struct file *file, int fd);
  46.202 -@@ -266,7 +264,7 @@ static int ep_events_transfer(struct eve
  46.203 - static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events,
  46.204 - 		   int maxevents, long timeout);
  46.205 - static int eventpollfs_delete_dentry(struct dentry *dentry);
  46.206 --static struct inode *ep_eventpoll_inode(void);
  46.207 -+static struct inode *ep_eventpoll_inode(struct file_operations *fops);
  46.208 - static struct super_block *eventpollfs_get_sb(struct file_system_type *fs_type,
  46.209 - 					      int flags, const char *dev_name,
  46.210 - 					      void *data);
  46.211 -@@ -525,7 +523,7 @@ asmlinkage long sys_epoll_create(int siz
  46.212 - 	 * Creates all the items needed to setup an eventpoll file. That is,
  46.213 - 	 * a file structure, and inode and a free file descriptor.
  46.214 - 	 */
  46.215 --	error = ep_getfd(&fd, &inode, &file, ep);
  46.216 -+	error = ep_getfd(&fd, &inode, &file, ep, &eventpoll_fops);
  46.217 - 	if (error)
  46.218 - 		goto eexit_2;
  46.219 - 
  46.220 -@@ -710,8 +708,8 @@ eexit_1:
  46.221 - /*
  46.222 -  * Creates the file descriptor to be used by the epoll interface.
  46.223 -  */
  46.224 --static int ep_getfd(int *efd, struct inode **einode, struct file **efile,
  46.225 --		    struct eventpoll *ep)
  46.226 -+int ep_getfd(int *efd, struct inode **einode, struct file **efile,
  46.227 -+		    struct eventpoll *ep, struct file_operations *fops)
  46.228 - {
  46.229 - 	struct qstr this;
  46.230 - 	char name[32];
  46.231 -@@ -727,7 +725,7 @@ static int ep_getfd(int *efd, struct ino
  46.232 - 		goto eexit_1;
  46.233 - 
  46.234 - 	/* Allocates an inode from the eventpoll file system */
  46.235 --	inode = ep_eventpoll_inode();
  46.236 -+	inode = ep_eventpoll_inode(fops);
  46.237 - 	error = PTR_ERR(inode);
  46.238 - 	if (IS_ERR(inode))
  46.239 - 		goto eexit_2;
  46.240 -@@ -758,7 +756,7 @@ static int ep_getfd(int *efd, struct ino
  46.241 - 
  46.242 - 	file->f_pos = 0;
  46.243 - 	file->f_flags = O_RDONLY;
  46.244 --	file->f_op = &eventpoll_fops;
  46.245 -+	file->f_op = fops;
  46.246 - 	file->f_mode = FMODE_READ;
  46.247 - 	file->f_version = 0;
  46.248 - 	file->private_data = ep;
  46.249 -@@ -1574,7 +1572,7 @@ static int eventpollfs_delete_dentry(str
  46.250 - }
  46.251 - 
  46.252 - 
  46.253 --static struct inode *ep_eventpoll_inode(void)
  46.254 -+static struct inode *ep_eventpoll_inode(struct file_operations *fops)
  46.255 - {
  46.256 - 	int error = -ENOMEM;
  46.257 - 	struct inode *inode = new_inode(eventpoll_mnt->mnt_sb);
  46.258 -@@ -1582,7 +1580,7 @@ static struct inode *ep_eventpoll_inode(
  46.259 - 	if (!inode)
  46.260 - 		goto eexit_1;
  46.261 - 
  46.262 --	inode->i_fop = &eventpoll_fops;
  46.263 -+	inode->i_fop = fops;
  46.264 - 
  46.265 - 	/*
  46.266 - 	 * Mark the inode dirty from the very beginning,
  46.267 -diff -pruN ../orig-linux-2.6.16.29/include/linux/aio.h ./include/linux/aio.h
  46.268 ---- ../orig-linux-2.6.16.29/include/linux/aio.h	2006-09-12 19:02:10.000000000 +0100
  46.269 -+++ ./include/linux/aio.h	2006-09-19 13:58:49.000000000 +0100
  46.270 -@@ -191,6 +191,11 @@ struct kioctx {
  46.271 - 	struct aio_ring_info	ring_info;
  46.272 - 
  46.273 - 	struct work_struct	wq;
  46.274 -+#ifdef CONFIG_EPOLL
  46.275 -+	// poll integration
  46.276 -+	wait_queue_head_t       poll_wait;
  46.277 -+	struct file		*file;
  46.278 -+#endif
  46.279 - };
  46.280 - 
  46.281 - /* prototypes */
  46.282 -diff -pruN ../orig-linux-2.6.16.29/include/linux/eventpoll.h ./include/linux/eventpoll.h
  46.283 ---- ../orig-linux-2.6.16.29/include/linux/eventpoll.h	2006-09-12 19:02:10.000000000 +0100
  46.284 -+++ ./include/linux/eventpoll.h	2006-09-19 13:58:49.000000000 +0100
  46.285 -@@ -86,6 +86,12 @@ static inline void eventpoll_release(str
  46.286 - }
  46.287 - 
  46.288 - 
  46.289 -+/*
  46.290 -+ * called by aio code to create fd that can poll the  aio event queueQ
  46.291 -+ */
  46.292 -+struct eventpoll;
  46.293 -+int ep_getfd(int *efd, struct inode **einode, struct file **efile,
  46.294 -+             struct eventpoll *ep, struct file_operations *fops);
  46.295 - #else
  46.296 - 
  46.297 - static inline void eventpoll_init_file(struct file *file) {}
    47.1 --- a/patches/linux-2.6.16.29/device_bind.patch	Mon Nov 27 10:10:57 2006 -0700
    47.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    47.3 @@ -1,15 +0,0 @@
    47.4 -diff -pruN ../orig-linux-2.6.16.29/drivers/base/bus.c ./drivers/base/bus.c
    47.5 ---- ../orig-linux-2.6.16.29/drivers/base/bus.c	2006-09-12 19:02:10.000000000 +0100
    47.6 -+++ ./drivers/base/bus.c	2006-09-19 13:58:54.000000000 +0100
    47.7 -@@ -188,6 +188,11 @@ static ssize_t driver_bind(struct device
    47.8 - 		up(&dev->sem);
    47.9 - 		if (dev->parent)
   47.10 - 			up(&dev->parent->sem);
   47.11 -+
   47.12 -+		if (err > 0) 		/* success */
   47.13 -+			err = count;
   47.14 -+		else if (err == 0)	/* driver didn't accept device */
   47.15 -+			err = -ENODEV;
   47.16 - 	}
   47.17 - 	put_device(dev);
   47.18 - 	put_bus(bus);
    48.1 --- a/patches/linux-2.6.16.29/fix-hz-suspend.patch	Mon Nov 27 10:10:57 2006 -0700
    48.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    48.3 @@ -1,26 +0,0 @@
    48.4 -diff -pruN ../orig-linux-2.6.16.29/kernel/timer.c ./kernel/timer.c
    48.5 ---- ../orig-linux-2.6.16.29/kernel/timer.c	2006-09-12 19:02:10.000000000 +0100
    48.6 -+++ ./kernel/timer.c	2006-09-19 13:58:58.000000000 +0100
    48.7 -@@ -555,6 +555,22 @@ found:
    48.8 - 	}
    48.9 - 	spin_unlock(&base->t_base.lock);
   48.10 - 
   48.11 -+	/*
   48.12 -+	 * It can happen that other CPUs service timer IRQs and increment
   48.13 -+	 * jiffies, but we have not yet got a local timer tick to process
   48.14 -+	 * the timer wheels.  In that case, the expiry time can be before
   48.15 -+	 * jiffies, but since the high-resolution timer here is relative to
   48.16 -+	 * jiffies, the default expression when high-resolution timers are
   48.17 -+	 * not active,
   48.18 -+	 *
   48.19 -+	 *   time_before(MAX_JIFFY_OFFSET + jiffies, expires)
   48.20 -+	 *
   48.21 -+	 * would falsely evaluate to true.  If that is the case, just
   48.22 -+	 * return jiffies so that we can immediately fire the local timer
   48.23 -+	 */
   48.24 -+	if (time_before(expires, jiffies))
   48.25 -+		return jiffies;
   48.26 -+
   48.27 - 	if (time_before(hr_expires, expires))
   48.28 - 		return hr_expires;
   48.29 - 
    49.1 --- a/patches/linux-2.6.16.29/fix-ide-cd-pio-mode.patch	Mon Nov 27 10:10:57 2006 -0700
    49.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    49.3 @@ -1,18 +0,0 @@
    49.4 -diff -pruN ../orig-linux-2.6.16.29/drivers/ide/ide-lib.c ./drivers/ide/ide-lib.c
    49.5 ---- ../orig-linux-2.6.16.29/drivers/ide/ide-lib.c	2006-09-12 19:02:10.000000000 +0100
    49.6 -+++ ./drivers/ide/ide-lib.c	2006-09-19 13:59:03.000000000 +0100
    49.7 -@@ -410,10 +410,10 @@ void ide_toggle_bounce(ide_drive_t *driv
    49.8 - {
    49.9 - 	u64 addr = BLK_BOUNCE_HIGH;	/* dma64_addr_t */
   49.10 - 
   49.11 --	if (!PCI_DMA_BUS_IS_PHYS) {
   49.12 --		addr = BLK_BOUNCE_ANY;
   49.13 --	} else if (on && drive->media == ide_disk) {
   49.14 --		if (HWIF(drive)->pci_dev)
   49.15 -+	if (on && drive->media == ide_disk) {
   49.16 -+		if (!PCI_DMA_BUS_IS_PHYS)
   49.17 -+			addr = BLK_BOUNCE_ANY;
   49.18 -+		else if (HWIF(drive)->pci_dev)
   49.19 - 			addr = HWIF(drive)->pci_dev->dma_mask;
   49.20 - 	}
   49.21 - 
    50.1 --- a/patches/linux-2.6.16.29/i386-mach-io-check-nmi.patch	Mon Nov 27 10:10:57 2006 -0700
    50.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    50.3 @@ -1,45 +0,0 @@
    50.4 -diff -pruN ../orig-linux-2.6.16.29/arch/i386/kernel/traps.c ./arch/i386/kernel/traps.c
    50.5 ---- ../orig-linux-2.6.16.29/arch/i386/kernel/traps.c	2006-09-12 19:02:10.000000000 +0100
    50.6 -+++ ./arch/i386/kernel/traps.c	2006-09-19 13:59:06.000000000 +0100
    50.7 -@@ -567,18 +567,11 @@ static void mem_parity_error(unsigned ch
    50.8 - 
    50.9 - static void io_check_error(unsigned char reason, struct pt_regs * regs)
   50.10 - {
   50.11 --	unsigned long i;
   50.12 --
   50.13 - 	printk(KERN_EMERG "NMI: IOCK error (debug interrupt?)\n");
   50.14 - 	show_registers(regs);
   50.15 - 
   50.16 - 	/* Re-enable the IOCK line, wait for a few seconds */
   50.17 --	reason = (reason & 0xf) | 8;
   50.18 --	outb(reason, 0x61);
   50.19 --	i = 2000;
   50.20 --	while (--i) udelay(1000);
   50.21 --	reason &= ~8;
   50.22 --	outb(reason, 0x61);
   50.23 -+	clear_io_check_error(reason);
   50.24 - }
   50.25 - 
   50.26 - static void unknown_nmi_error(unsigned char reason, struct pt_regs * regs)
   50.27 -diff -pruN ../orig-linux-2.6.16.29/include/asm-i386/mach-default/mach_traps.h ./include/asm-i386/mach-default/mach_traps.h
   50.28 ---- ../orig-linux-2.6.16.29/include/asm-i386/mach-default/mach_traps.h	2006-09-12 19:02:10.000000000 +0100
   50.29 -+++ ./include/asm-i386/mach-default/mach_traps.h	2006-09-19 13:59:06.000000000 +0100
   50.30 -@@ -15,6 +15,18 @@ static inline void clear_mem_error(unsig
   50.31 - 	outb(reason, 0x61);
   50.32 - }
   50.33 - 
   50.34 -+static inline void clear_io_check_error(unsigned char reason)
   50.35 -+{
   50.36 -+	unsigned long i;
   50.37 -+
   50.38 -+	reason = (reason & 0xf) | 8;
   50.39 -+	outb(reason, 0x61);
   50.40 -+	i = 2000;
   50.41 -+	while (--i) udelay(1000);
   50.42 -+	reason &= ~8;
   50.43 -+	outb(reason, 0x61);
   50.44 -+}
   50.45 -+
   50.46 - static inline unsigned char get_nmi_reason(void)
   50.47 - {
   50.48 - 	return inb(0x61);
    51.1 --- a/patches/linux-2.6.16.29/ipv6-no-autoconf.patch	Mon Nov 27 10:10:57 2006 -0700
    51.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    51.3 @@ -1,19 +0,0 @@
    51.4 -diff -pruN ../orig-linux-2.6.16.29/net/ipv6/addrconf.c ./net/ipv6/addrconf.c
    51.5 ---- ../orig-linux-2.6.16.29/net/ipv6/addrconf.c	2006-09-12 19:02:10.000000000 +0100
    51.6 -+++ ./net/ipv6/addrconf.c	2006-09-19 13:59:11.000000000 +0100
    51.7 -@@ -2471,6 +2471,7 @@ static void addrconf_dad_start(struct in
    51.8 - 	spin_lock_bh(&ifp->lock);
    51.9 - 
   51.10 - 	if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) ||
   51.11 -+	    !(dev->flags&IFF_MULTICAST) ||
   51.12 - 	    !(ifp->flags&IFA_F_TENTATIVE)) {
   51.13 - 		ifp->flags &= ~IFA_F_TENTATIVE;
   51.14 - 		spin_unlock_bh(&ifp->lock);
   51.15 -@@ -2555,6 +2556,7 @@ static void addrconf_dad_completed(struc
   51.16 - 	if (ifp->idev->cnf.forwarding == 0 &&
   51.17 - 	    ifp->idev->cnf.rtr_solicits > 0 &&
   51.18 - 	    (dev->flags&IFF_LOOPBACK) == 0 &&
   51.19 -+	    (dev->flags & IFF_MULTICAST) &&
   51.20 - 	    (ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL)) {
   51.21 - 		struct in6_addr all_routers;
   51.22 - 
    52.1 --- a/patches/linux-2.6.16.29/net-csum.patch	Mon Nov 27 10:10:57 2006 -0700
    52.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    52.3 @@ -1,63 +0,0 @@
    52.4 -diff -pruN ../orig-linux-2.6.16.29/net/ipv4/netfilter/ip_nat_proto_tcp.c ./net/ipv4/netfilter/ip_nat_proto_tcp.c
    52.5 ---- ../orig-linux-2.6.16.29/net/ipv4/netfilter/ip_nat_proto_tcp.c	2006-09-12 19:02:10.000000000 +0100
    52.6 -+++ ./net/ipv4/netfilter/ip_nat_proto_tcp.c	2006-09-19 13:59:15.000000000 +0100
    52.7 -@@ -129,7 +129,12 @@ tcp_manip_pkt(struct sk_buff **pskb,
    52.8 - 	if (hdrsize < sizeof(*hdr))
    52.9 - 		return 1;
   52.10 - 
   52.11 --	hdr->check = ip_nat_cheat_check(~oldip, newip,
   52.12 -+#ifdef CONFIG_XEN
   52.13 -+	if ((*pskb)->proto_csum_blank)
   52.14 -+		hdr->check = ip_nat_cheat_check(oldip, ~newip, hdr->check);
   52.15 -+	else
   52.16 -+#endif
   52.17 -+		hdr->check = ip_nat_cheat_check(~oldip, newip,
   52.18 - 					ip_nat_cheat_check(oldport ^ 0xFFFF,
   52.19 - 							   newport,
   52.20 - 							   hdr->check));
   52.21 -diff -pruN ../orig-linux-2.6.16.29/net/ipv4/netfilter/ip_nat_proto_udp.c ./net/ipv4/netfilter/ip_nat_proto_udp.c
   52.22 ---- ../orig-linux-2.6.16.29/net/ipv4/netfilter/ip_nat_proto_udp.c	2006-09-12 19:02:10.000000000 +0100
   52.23 -+++ ./net/ipv4/netfilter/ip_nat_proto_udp.c	2006-09-19 13:59:15.000000000 +0100
   52.24 -@@ -113,11 +113,17 @@ udp_manip_pkt(struct sk_buff **pskb,
   52.25 - 		newport = tuple->dst.u.udp.port;
   52.26 - 		portptr = &hdr->dest;
   52.27 - 	}
   52.28 --	if (hdr->check) /* 0 is a special case meaning no checksum */
   52.29 --		hdr->check = ip_nat_cheat_check(~oldip, newip,
   52.30 -+	if (hdr->check) { /* 0 is a special case meaning no checksum */
   52.31 -+#ifdef CONFIG_XEN
   52.32 -+		if ((*pskb)->proto_csum_blank)
   52.33 -+			hdr->check = ip_nat_cheat_check(oldip, ~newip, hdr->check);
   52.34 -+		else
   52.35 -+#endif
   52.36 -+			hdr->check = ip_nat_cheat_check(~oldip, newip,
   52.37 - 					ip_nat_cheat_check(*portptr ^ 0xFFFF,
   52.38 - 							   newport,
   52.39 - 							   hdr->check));
   52.40 -+	}
   52.41 - 	*portptr = newport;
   52.42 - 	return 1;
   52.43 - }
   52.44 -diff -pruN ../orig-linux-2.6.16.29/net/ipv4/xfrm4_output.c ./net/ipv4/xfrm4_output.c
   52.45 ---- ../orig-linux-2.6.16.29/net/ipv4/xfrm4_output.c	2006-09-12 19:02:10.000000000 +0100
   52.46 -+++ ./net/ipv4/xfrm4_output.c	2006-09-19 13:59:15.000000000 +0100
   52.47 -@@ -17,6 +17,8 @@
   52.48 - #include <net/xfrm.h>
   52.49 - #include <net/icmp.h>
   52.50 - 
   52.51 -+extern int skb_checksum_setup(struct sk_buff *skb);
   52.52 -+
   52.53 - /* Add encapsulation header.
   52.54 -  *
   52.55 -  * In transport mode, the IP header will be moved forward to make space
   52.56 -@@ -103,6 +105,10 @@ static int xfrm4_output_one(struct sk_bu
   52.57 - 	struct xfrm_state *x = dst->xfrm;
   52.58 - 	int err;
   52.59 - 	
   52.60 -+	err = skb_checksum_setup(skb);
   52.61 -+	if (err)
   52.62 -+		goto error_nolock;
   52.63 -+
   52.64 - 	if (skb->ip_summed == CHECKSUM_HW) {
   52.65 - 		err = skb_checksum_help(skb, 0);
   52.66 - 		if (err)
    53.1 --- a/patches/linux-2.6.16.29/net-gso-0-base.patch	Mon Nov 27 10:10:57 2006 -0700
    53.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    53.3 @@ -1,2835 +0,0 @@
    53.4 -diff -pruN ../orig-linux-2.6.16.29/Documentation/networking/netdevices.txt ./Documentation/networking/netdevices.txt
    53.5 ---- ../orig-linux-2.6.16.29/Documentation/networking/netdevices.txt	2006-09-12 19:02:10.000000000 +0100
    53.6 -+++ ./Documentation/networking/netdevices.txt	2006-09-19 13:59:20.000000000 +0100
    53.7 -@@ -42,9 +42,9 @@ dev->get_stats:
    53.8 - 	Context: nominally process, but don't sleep inside an rwlock
    53.9 - 
   53.10 - dev->hard_start_xmit:
   53.11 --	Synchronization: dev->xmit_lock spinlock.
   53.12 -+	Synchronization: netif_tx_lock spinlock.
   53.13 - 	When the driver sets NETIF_F_LLTX in dev->features this will be
   53.14 --	called without holding xmit_lock. In this case the driver 
   53.15 -+	called without holding netif_tx_lock. In this case the driver
   53.16 - 	has to lock by itself when needed. It is recommended to use a try lock
   53.17 - 	for this and return -1 when the spin lock fails. 
   53.18 - 	The locking there should also properly protect against 
   53.19 -@@ -62,12 +62,12 @@ dev->hard_start_xmit:
   53.20 - 	  Only valid when NETIF_F_LLTX is set.
   53.21 - 
   53.22 - dev->tx_timeout:
   53.23 --	Synchronization: dev->xmit_lock spinlock.
   53.24 -+	Synchronization: netif_tx_lock spinlock.
   53.25 - 	Context: BHs disabled
   53.26 - 	Notes: netif_queue_stopped() is guaranteed true
   53.27 - 
   53.28 - dev->set_multicast_list:
   53.29 --	Synchronization: dev->xmit_lock spinlock.
   53.30 -+	Synchronization: netif_tx_lock spinlock.
   53.31 - 	Context: BHs disabled
   53.32 - 
   53.33 - dev->poll:
   53.34 -diff -pruN ../orig-linux-2.6.16.29/drivers/block/aoe/aoenet.c ./drivers/block/aoe/aoenet.c
   53.35 ---- ../orig-linux-2.6.16.29/drivers/block/aoe/aoenet.c	2006-09-12 19:02:10.000000000 +0100
   53.36 -+++ ./drivers/block/aoe/aoenet.c	2006-09-19 13:59:20.000000000 +0100
   53.37 -@@ -95,9 +95,8 @@ mac_addr(char addr[6])
   53.38 - static struct sk_buff *
   53.39 - skb_check(struct sk_buff *skb)
   53.40 - {
   53.41 --	if (skb_is_nonlinear(skb))
   53.42 - 	if ((skb = skb_share_check(skb, GFP_ATOMIC)))
   53.43 --	if (skb_linearize(skb, GFP_ATOMIC) < 0) {
   53.44 -+	if (skb_linearize(skb)) {
   53.45 - 		dev_kfree_skb(skb);
   53.46 - 		return NULL;
   53.47 - 	}
   53.48 -diff -pruN ../orig-linux-2.6.16.29/drivers/infiniband/ulp/ipoib/ipoib_multicast.c ./drivers/infiniband/ulp/ipoib/ipoib_multicast.c
   53.49 ---- ../orig-linux-2.6.16.29/drivers/infiniband/ulp/ipoib/ipoib_multicast.c	2006-09-12 19:02:10.000000000 +0100
   53.50 -+++ ./drivers/infiniband/ulp/ipoib/ipoib_multicast.c	2006-09-19 13:59:20.000000000 +0100
   53.51 -@@ -821,7 +821,8 @@ void ipoib_mcast_restart_task(void *dev_
   53.52 - 
   53.53 - 	ipoib_mcast_stop_thread(dev, 0);
   53.54 - 
   53.55 --	spin_lock_irqsave(&dev->xmit_lock, flags);
   53.56 -+	local_irq_save(flags);
   53.57 -+	netif_tx_lock(dev);
   53.58 - 	spin_lock(&priv->lock);
   53.59 - 
   53.60 - 	/*
   53.61 -@@ -896,7 +897,8 @@ void ipoib_mcast_restart_task(void *dev_
   53.62 - 	}
   53.63 - 
   53.64 - 	spin_unlock(&priv->lock);
   53.65 --	spin_unlock_irqrestore(&dev->xmit_lock, flags);
   53.66 -+	netif_tx_unlock(dev);
   53.67 -+	local_irq_restore(flags);
   53.68 - 
   53.69 - 	/* We have to cancel outside of the spinlock */
   53.70 - 	list_for_each_entry_safe(mcast, tmcast, &remove_list, list) {
   53.71 -diff -pruN ../orig-linux-2.6.16.29/drivers/media/dvb/dvb-core/dvb_net.c ./drivers/media/dvb/dvb-core/dvb_net.c
   53.72 ---- ../orig-linux-2.6.16.29/drivers/media/dvb/dvb-core/dvb_net.c	2006-09-12 19:02:10.000000000 +0100
   53.73 -+++ ./drivers/media/dvb/dvb-core/dvb_net.c	2006-09-19 13:59:20.000000000 +0100
   53.74 -@@ -1052,7 +1052,7 @@ static void wq_set_multicast_list (void 
   53.75 - 
   53.76 - 	dvb_net_feed_stop(dev);
   53.77 - 	priv->rx_mode = RX_MODE_UNI;
   53.78 --	spin_lock_bh(&dev->xmit_lock);
   53.79 -+	netif_tx_lock_bh(dev);
   53.80 - 
   53.81 - 	if (dev->flags & IFF_PROMISC) {
   53.82 - 		dprintk("%s: promiscuous mode\n", dev->name);
   53.83 -@@ -1077,7 +1077,7 @@ static void wq_set_multicast_list (void 
   53.84 - 		}
   53.85 - 	}
   53.86 - 
   53.87 --	spin_unlock_bh(&dev->xmit_lock);
   53.88 -+	netif_tx_unlock_bh(dev);
   53.89 - 	dvb_net_feed_start(dev);
   53.90 - }
   53.91 - 
   53.92 -diff -pruN ../orig-linux-2.6.16.29/drivers/net/8139cp.c ./drivers/net/8139cp.c
   53.93 ---- ../orig-linux-2.6.16.29/drivers/net/8139cp.c	2006-09-12 19:02:10.000000000 +0100
   53.94 -+++ ./drivers/net/8139cp.c	2006-09-19 13:59:20.000000000 +0100
   53.95 -@@ -794,7 +794,7 @@ static int cp_start_xmit (struct sk_buff
   53.96 - 	entry = cp->tx_head;
   53.97 - 	eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0;
   53.98 - 	if (dev->features & NETIF_F_TSO)
   53.99 --		mss = skb_shinfo(skb)->tso_size;
  53.100 -+		mss = skb_shinfo(skb)->gso_size;
  53.101 - 
  53.102 - 	if (skb_shinfo(skb)->nr_frags == 0) {
  53.103 - 		struct cp_desc *txd = &cp->tx_ring[entry];
  53.104 -diff -pruN ../orig-linux-2.6.16.29/drivers/net/bnx2.c ./drivers/net/bnx2.c
  53.105 ---- ../orig-linux-2.6.16.29/drivers/net/bnx2.c	2006-09-12 19:02:10.000000000 +0100
  53.106 -+++ ./drivers/net/bnx2.c	2006-09-19 13:59:20.000000000 +0100
  53.107 -@@ -1593,7 +1593,7 @@ bnx2_tx_int(struct bnx2 *bp)
  53.108 - 		skb = tx_buf->skb;
  53.109 - #ifdef BCM_TSO 
  53.110 - 		/* partial BD completions possible with TSO packets */
  53.111 --		if (skb_shinfo(skb)->tso_size) {
  53.112 -+		if (skb_shinfo(skb)->gso_size) {
  53.113 - 			u16 last_idx, last_ring_idx;
  53.114 - 
  53.115 - 			last_idx = sw_cons +
  53.116 -@@ -1948,7 +1948,7 @@ bnx2_poll(struct net_device *dev, int *b
  53.117 - 	return 1;
  53.118 - }
  53.119 - 
  53.120 --/* Called with rtnl_lock from vlan functions and also dev->xmit_lock
  53.121 -+/* Called with rtnl_lock from vlan functions and also netif_tx_lock
  53.122 -  * from set_multicast.
  53.123 -  */
  53.124 - static void
  53.125 -@@ -4403,7 +4403,7 @@ bnx2_vlan_rx_kill_vid(struct net_device 
  53.126 - }
  53.127 - #endif
  53.128 - 
  53.129 --/* Called with dev->xmit_lock.
  53.130 -+/* Called with netif_tx_lock.
  53.131 -  * hard_start_xmit is pseudo-lockless - a lock is only required when
  53.132 -  * the tx queue is full. This way, we get the benefit of lockless
  53.133 -  * operations most of the time without the complexities to handle
  53.134 -@@ -4441,7 +4441,7 @@ bnx2_start_xmit(struct sk_buff *skb, str
  53.135 - 			(TX_BD_FLAGS_VLAN_TAG | (vlan_tx_tag_get(skb) << 16));
  53.136 - 	}
  53.137 - #ifdef BCM_TSO 
  53.138 --	if ((mss = skb_shinfo(skb)->tso_size) &&
  53.139 -+	if ((mss = skb_shinfo(skb)->gso_size) &&
  53.140 - 		(skb->len > (bp->dev->mtu + ETH_HLEN))) {
  53.141 - 		u32 tcp_opt_len, ip_tcp_len;
  53.142 - 
  53.143 -diff -pruN ../orig-linux-2.6.16.29/drivers/net/bonding/bond_main.c ./drivers/net/bonding/bond_main.c
  53.144 ---- ../orig-linux-2.6.16.29/drivers/net/bonding/bond_main.c	2006-09-12 19:02:10.000000000 +0100
  53.145 -+++ ./drivers/net/bonding/bond_main.c	2006-09-19 13:59:20.000000000 +0100
  53.146 -@@ -1145,8 +1145,7 @@ int bond_sethwaddr(struct net_device *bo
  53.147 - }
  53.148 - 
  53.149 - #define BOND_INTERSECT_FEATURES \
  53.150 --	(NETIF_F_SG|NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM|\
  53.151 --	NETIF_F_TSO|NETIF_F_UFO)
  53.152 -+	(NETIF_F_SG | NETIF_F_ALL_CSUM | NETIF_F_TSO | NETIF_F_UFO)
  53.153 - 
  53.154 - /* 
  53.155 -  * Compute the common dev->feature set available to all slaves.  Some
  53.156 -@@ -1164,9 +1163,7 @@ static int bond_compute_features(struct 
  53.157 - 		features &= (slave->dev->features & BOND_INTERSECT_FEATURES);
  53.158 - 
  53.159 - 	if ((features & NETIF_F_SG) && 
  53.160 --	    !(features & (NETIF_F_IP_CSUM |
  53.161 --			  NETIF_F_NO_CSUM |
  53.162 --			  NETIF_F_HW_CSUM)))
  53.163 -+	    !(features & NETIF_F_ALL_CSUM))
  53.164 - 		features &= ~NETIF_F_SG;
  53.165 - 
  53.166 - 	/* 
  53.167 -@@ -4147,7 +4144,7 @@ static int bond_init(struct net_device *
  53.168 - 	 */
  53.169 - 	bond_dev->features |= NETIF_F_VLAN_CHALLENGED;
  53.170 - 
  53.171 --	/* don't acquire bond device's xmit_lock when 
  53.172 -+	/* don't acquire bond device's netif_tx_lock when
  53.173 - 	 * transmitting */
  53.174 - 	bond_dev->features |= NETIF_F_LLTX;
  53.175 - 
  53.176 -diff -pruN ../orig-linux-2.6.16.29/drivers/net/chelsio/sge.c ./drivers/net/chelsio/sge.c
  53.177 ---- ../orig-linux-2.6.16.29/drivers/net/chelsio/sge.c	2006-09-12 19:02:10.000000000 +0100
  53.178 -+++ ./drivers/net/chelsio/sge.c	2006-09-19 13:59:20.000000000 +0100
  53.179 -@@ -1419,7 +1419,7 @@ int t1_start_xmit(struct sk_buff *skb, s
  53.180 - 	struct cpl_tx_pkt *cpl;
  53.181 - 
  53.182 - #ifdef NETIF_F_TSO
  53.183 --	if (skb_shinfo(skb)->tso_size) {
  53.184 -+	if (skb_shinfo(skb)->gso_size) {
  53.185 - 		int eth_type;
  53.186 - 		struct cpl_tx_pkt_lso *hdr;
  53.187 - 
  53.188 -@@ -1434,7 +1434,7 @@ int t1_start_xmit(struct sk_buff *skb, s
  53.189 - 		hdr->ip_hdr_words = skb->nh.iph->ihl;
  53.190 - 		hdr->tcp_hdr_words = skb->h.th->doff;
  53.191 - 		hdr->eth_type_mss = htons(MK_ETH_TYPE_MSS(eth_type,
  53.192 --						skb_shinfo(skb)->tso_size));
  53.193 -+						skb_shinfo(skb)->gso_size));
  53.194 - 		hdr->len = htonl(skb->len - sizeof(*hdr));
  53.195 - 		cpl = (struct cpl_tx_pkt *)hdr;
  53.196 - 		sge->stats.tx_lso_pkts++;
  53.197 -diff -pruN ../orig-linux-2.6.16.29/drivers/net/e1000/e1000_main.c ./drivers/net/e1000/e1000_main.c
  53.198 ---- ../orig-linux-2.6.16.29/drivers/net/e1000/e1000_main.c	2006-09-12 19:02:10.000000000 +0100
  53.199 -+++ ./drivers/net/e1000/e1000_main.c	2006-09-19 13:59:20.000000000 +0100
  53.200 -@@ -2526,7 +2526,7 @@ e1000_tso(struct e1000_adapter *adapter,
  53.201 - 	uint8_t ipcss, ipcso, tucss, tucso, hdr_len;
  53.202 - 	int err;
  53.203 - 
  53.204 --	if (skb_shinfo(skb)->tso_size) {
  53.205 -+	if (skb_shinfo(skb)->gso_size) {
  53.206 - 		if (skb_header_cloned(skb)) {
  53.207 - 			err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
  53.208 - 			if (err)
  53.209 -@@ -2534,7 +2534,7 @@ e1000_tso(struct e1000_adapter *adapter,
  53.210 - 		}
  53.211 - 
  53.212 - 		hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
  53.213 --		mss = skb_shinfo(skb)->tso_size;
  53.214 -+		mss = skb_shinfo(skb)->gso_size;
  53.215 - 		if (skb->protocol == ntohs(ETH_P_IP)) {
  53.216 - 			skb->nh.iph->tot_len = 0;
  53.217 - 			skb->nh.iph->check = 0;
  53.218 -@@ -2651,7 +2651,7 @@ e1000_tx_map(struct e1000_adapter *adapt
  53.219 - 		 * tso gets written back prematurely before the data is fully
  53.220 - 		 * DMAd to the controller */
  53.221 - 		if (!skb->data_len && tx_ring->last_tx_tso &&
  53.222 --				!skb_shinfo(skb)->tso_size) {
  53.223 -+				!skb_shinfo(skb)->gso_size) {
  53.224 - 			tx_ring->last_tx_tso = 0;
  53.225 - 			size -= 4;
  53.226 - 		}
  53.227 -@@ -2893,7 +2893,7 @@ e1000_xmit_frame(struct sk_buff *skb, st
  53.228 - 	}
  53.229 - 
  53.230 - #ifdef NETIF_F_TSO
  53.231 --	mss = skb_shinfo(skb)->tso_size;
  53.232 -+	mss = skb_shinfo(skb)->gso_size;
  53.233 - 	/* The controller does a simple calculation to 
  53.234 - 	 * make sure there is enough room in the FIFO before
  53.235 - 	 * initiating the DMA for each buffer.  The calc is:
  53.236 -@@ -2935,7 +2935,7 @@ e1000_xmit_frame(struct sk_buff *skb, st
  53.237 - #ifdef NETIF_F_TSO
  53.238 - 	/* Controller Erratum workaround */
  53.239 - 	if (!skb->data_len && tx_ring->last_tx_tso &&
  53.240 --		!skb_shinfo(skb)->tso_size)
  53.241 -+		!skb_shinfo(skb)->gso_size)
  53.242 - 		count++;
  53.243 - #endif
  53.244 - 
  53.245 -diff -pruN ../orig-linux-2.6.16.29/drivers/net/forcedeth.c ./drivers/net/forcedeth.c
  53.246 ---- ../orig-linux-2.6.16.29/drivers/net/forcedeth.c	2006-09-12 19:02:10.000000000 +0100
  53.247 -+++ ./drivers/net/forcedeth.c	2006-09-19 13:59:20.000000000 +0100
  53.248 -@@ -482,9 +482,9 @@ typedef union _ring_type {
  53.249 -  * critical parts:
  53.250 -  * - rx is (pseudo-) lockless: it relies on the single-threading provided
  53.251 -  *	by the arch code for interrupts.
  53.252 -- * - tx setup is lockless: it relies on dev->xmit_lock. Actual submission
  53.253 -+ * - tx setup is lockless: it relies on netif_tx_lock. Actual submission
  53.254 -  *	needs dev->priv->lock :-(
  53.255 -- * - set_multicast_list: preparation lockless, relies on dev->xmit_lock.
  53.256 -+ * - set_multicast_list: preparation lockless, relies on netif_tx_lock.
  53.257 -  */
  53.258 - 
  53.259 - /* in dev: base, irq */
  53.260 -@@ -1016,7 +1016,7 @@ static void drain_ring(struct net_device
  53.261 - 
  53.262 - /*
  53.263 -  * nv_start_xmit: dev->hard_start_xmit function
  53.264 -- * Called with dev->xmit_lock held.
  53.265 -+ * Called with netif_tx_lock held.
  53.266 -  */
  53.267 - static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
  53.268 - {
  53.269 -@@ -1105,8 +1105,8 @@ static int nv_start_xmit(struct sk_buff 
  53.270 - 	np->tx_skbuff[nr] = skb;
  53.271 - 
  53.272 - #ifdef NETIF_F_TSO
  53.273 --	if (skb_shinfo(skb)->tso_size)
  53.274 --		tx_flags_extra = NV_TX2_TSO | (skb_shinfo(skb)->tso_size << NV_TX2_TSO_SHIFT);
  53.275 -+	if (skb_shinfo(skb)->gso_size)
  53.276 -+		tx_flags_extra = NV_TX2_TSO | (skb_shinfo(skb)->gso_size << NV_TX2_TSO_SHIFT);
  53.277 - 	else
  53.278 - #endif
  53.279 - 	tx_flags_extra = (skb->ip_summed == CHECKSUM_HW ? (NV_TX2_CHECKSUM_L3|NV_TX2_CHECKSUM_L4) : 0);
  53.280 -@@ -1203,7 +1203,7 @@ static void nv_tx_done(struct net_device
  53.281 - 
  53.282 - /*
  53.283 -  * nv_tx_timeout: dev->tx_timeout function
  53.284 -- * Called with dev->xmit_lock held.
  53.285 -+ * Called with netif_tx_lock held.
  53.286 -  */
  53.287 - static void nv_tx_timeout(struct net_device *dev)
  53.288 - {
  53.289 -@@ -1524,7 +1524,7 @@ static int nv_change_mtu(struct net_devi
  53.290 - 		 * Changing the MTU is a rare event, it shouldn't matter.
  53.291 - 		 */
  53.292 - 		disable_irq(dev->irq);
  53.293 --		spin_lock_bh(&dev->xmit_lock);
  53.294 -+		netif_tx_lock_bh(dev);
  53.295 - 		spin_lock(&np->lock);
  53.296 - 		/* stop engines */
  53.297 - 		nv_stop_rx(dev);
  53.298 -@@ -1559,7 +1559,7 @@ static int nv_change_mtu(struct net_devi
  53.299 - 		nv_start_rx(dev);
  53.300 - 		nv_start_tx(dev);
  53.301 - 		spin_unlock(&np->lock);
  53.302 --		spin_unlock_bh(&dev->xmit_lock);
  53.303 -+		netif_tx_unlock_bh(dev);
  53.304 - 		enable_irq(dev->irq);
  53.305 - 	}
  53.306 - 	return 0;
  53.307 -@@ -1594,7 +1594,7 @@ static int nv_set_mac_address(struct net
  53.308 - 	memcpy(dev->dev_addr, macaddr->sa_data, ETH_ALEN);
  53.309 - 
  53.310 - 	if (netif_running(dev)) {
  53.311 --		spin_lock_bh(&dev->xmit_lock);
  53.312 -+		netif_tx_lock_bh(dev);
  53.313 - 		spin_lock_irq(&np->lock);
  53.314 - 
  53.315 - 		/* stop rx engine */
  53.316 -@@ -1606,7 +1606,7 @@ static int nv_set_mac_address(struct net
  53.317 - 		/* restart rx engine */
  53.318 - 		nv_start_rx(dev);
  53.319 - 		spin_unlock_irq(&np->lock);
  53.320 --		spin_unlock_bh(&dev->xmit_lock);
  53.321 -+		netif_tx_unlock_bh(dev);
  53.322 - 	} else {
  53.323 - 		nv_copy_mac_to_hw(dev);
  53.324 - 	}
  53.325 -@@ -1615,7 +1615,7 @@ static int nv_set_mac_address(struct net
  53.326 - 
  53.327 - /*
  53.328 -  * nv_set_multicast: dev->set_multicast function
  53.329 -- * Called with dev->xmit_lock held.
  53.330 -+ * Called with netif_tx_lock held.
  53.331 -  */
  53.332 - static void nv_set_multicast(struct net_device *dev)
  53.333 - {
  53.334 -diff -pruN ../orig-linux-2.6.16.29/drivers/net/hamradio/6pack.c ./drivers/net/hamradio/6pack.c
  53.335 ---- ../orig-linux-2.6.16.29/drivers/net/hamradio/6pack.c	2006-09-12 19:02:10.000000000 +0100
  53.336 -+++ ./drivers/net/hamradio/6pack.c	2006-09-19 13:59:20.000000000 +0100
  53.337 -@@ -308,9 +308,9 @@ static int sp_set_mac_address(struct net
  53.338 - {
  53.339 - 	struct sockaddr_ax25 *sa = addr;
  53.340 - 
  53.341 --	spin_lock_irq(&dev->xmit_lock);
  53.342 -+	netif_tx_lock_bh(dev);
  53.343 - 	memcpy(dev->dev_addr, &sa->sax25_call, AX25_ADDR_LEN);
  53.344 --	spin_unlock_irq(&dev->xmit_lock);
  53.345 -+	netif_tx_unlock_bh(dev);
  53.346 - 
  53.347 - 	return 0;
  53.348 - }
  53.349 -@@ -767,9 +767,9 @@ static int sixpack_ioctl(struct tty_stru
  53.350 - 			break;
  53.351 - 		}
  53.352 - 
  53.353 --		spin_lock_irq(&dev->xmit_lock);
  53.354 -+		netif_tx_lock_bh(dev);
  53.355 - 		memcpy(dev->dev_addr, &addr, AX25_ADDR_LEN);
  53.356 --		spin_unlock_irq(&dev->xmit_lock);
  53.357 -+		netif_tx_unlock_bh(dev);
  53.358 - 
  53.359 - 		err = 0;
  53.360 - 		break;
  53.361 -diff -pruN ../orig-linux-2.6.16.29/drivers/net/hamradio/mkiss.c ./drivers/net/hamradio/mkiss.c
  53.362 ---- ../orig-linux-2.6.16.29/drivers/net/hamradio/mkiss.c	2006-09-12 19:02:10.000000000 +0100
  53.363 -+++ ./drivers/net/hamradio/mkiss.c	2006-09-19 13:59:20.000000000 +0100
  53.364 -@@ -357,9 +357,9 @@ static int ax_set_mac_address(struct net
  53.365 - {
  53.366 - 	struct sockaddr_ax25 *sa = addr;
  53.367 - 
  53.368 --	spin_lock_irq(&dev->xmit_lock);
  53.369 -+	netif_tx_lock_bh(dev);
  53.370 - 	memcpy(dev->dev_addr, &sa->sax25_call, AX25_ADDR_LEN);
  53.371 --	spin_unlock_irq(&dev->xmit_lock);
  53.372 -+	netif_tx_unlock_bh(dev);
  53.373 - 
  53.374 - 	return 0;
  53.375 - }
  53.376 -@@ -886,9 +886,9 @@ static int mkiss_ioctl(struct tty_struct
  53.377 - 			break;
  53.378 - 		}
  53.379 - 
  53.380 --		spin_lock_irq(&dev->xmit_lock);
  53.381 -+		netif_tx_lock_bh(dev);
  53.382 - 		memcpy(dev->dev_addr, addr, AX25_ADDR_LEN);
  53.383 --		spin_unlock_irq(&dev->xmit_lock);
  53.384 -+		netif_tx_unlock_bh(dev);
  53.385 - 
  53.386 - 		err = 0;
  53.387 - 		break;
  53.388 -diff -pruN ../orig-linux-2.6.16.29/drivers/net/ifb.c ./drivers/net/ifb.c
  53.389 ---- ../orig-linux-2.6.16.29/drivers/net/ifb.c	2006-09-12 19:02:10.000000000 +0100
  53.390 -+++ ./drivers/net/ifb.c	2006-09-19 13:59:20.000000000 +0100
  53.391 -@@ -76,13 +76,13 @@ static void ri_tasklet(unsigned long dev
  53.392 - 	dp->st_task_enter++;
  53.393 - 	if ((skb = skb_peek(&dp->tq)) == NULL) {
  53.394 - 		dp->st_txq_refl_try++;
  53.395 --		if (spin_trylock(&_dev->xmit_lock)) {
  53.396 -+		if (netif_tx_trylock(_dev)) {
  53.397 - 			dp->st_rxq_enter++;
  53.398 - 			while ((skb = skb_dequeue(&dp->rq)) != NULL) {
  53.399 - 				skb_queue_tail(&dp->tq, skb);
  53.400 - 				dp->st_rx2tx_tran++;
  53.401 - 			}
  53.402 --			spin_unlock(&_dev->xmit_lock);
  53.403 -+			netif_tx_unlock(_dev);
  53.404 - 		} else {
  53.405 - 			/* reschedule */
  53.406 - 			dp->st_rxq_notenter++;
  53.407 -@@ -110,7 +110,7 @@ static void ri_tasklet(unsigned long dev
  53.408 - 		}
  53.409 - 	}
  53.410 - 
  53.411 --	if (spin_trylock(&_dev->xmit_lock)) {
  53.412 -+	if (netif_tx_trylock(_dev)) {
  53.413 - 		dp->st_rxq_check++;
  53.414 - 		if ((skb = skb_peek(&dp->rq)) == NULL) {
  53.415 - 			dp->tasklet_pending = 0;
  53.416 -@@ -118,10 +118,10 @@ static void ri_tasklet(unsigned long dev
  53.417 - 				netif_wake_queue(_dev);
  53.418 - 		} else {
  53.419 - 			dp->st_rxq_rsch++;
  53.420 --			spin_unlock(&_dev->xmit_lock);
  53.421 -+			netif_tx_unlock(_dev);
  53.422 - 			goto resched;
  53.423 - 		}
  53.424 --		spin_unlock(&_dev->xmit_lock);
  53.425 -+		netif_tx_unlock(_dev);
  53.426 - 	} else {
  53.427 - resched:
  53.428 - 		dp->tasklet_pending = 1;
  53.429 -diff -pruN ../orig-linux-2.6.16.29/drivers/net/irda/vlsi_ir.c ./drivers/net/irda/vlsi_ir.c
  53.430 ---- ../orig-linux-2.6.16.29/drivers/net/irda/vlsi_ir.c	2006-09-12 19:02:10.000000000 +0100
  53.431 -+++ ./drivers/net/irda/vlsi_ir.c	2006-09-19 13:59:20.000000000 +0100
  53.432 -@@ -959,7 +959,7 @@ static int vlsi_hard_start_xmit(struct s
  53.433 - 			    ||  (now.tv_sec==ready.tv_sec && now.tv_usec>=ready.tv_usec))
  53.434 - 			    	break;
  53.435 - 			udelay(100);
  53.436 --			/* must not sleep here - we are called under xmit_lock! */
  53.437 -+			/* must not sleep here - called under netif_tx_lock! */
  53.438 - 		}
  53.439 - 	}
  53.440 - 
  53.441 -diff -pruN ../orig-linux-2.6.16.29/drivers/net/ixgb/ixgb_main.c ./drivers/net/ixgb/ixgb_main.c
  53.442 ---- ../orig-linux-2.6.16.29/drivers/net/ixgb/ixgb_main.c	2006-09-12 19:02:10.000000000 +0100
  53.443 -+++ ./drivers/net/ixgb/ixgb_main.c	2006-09-19 13:59:20.000000000 +0100
  53.444 -@@ -1163,7 +1163,7 @@ ixgb_tso(struct ixgb_adapter *adapter, s
  53.445 - 	uint16_t ipcse, tucse, mss;
  53.446 - 	int err;
  53.447 - 
  53.448 --	if(likely(skb_shinfo(skb)->tso_size)) {
  53.449 -+	if(likely(skb_shinfo(skb)->gso_size)) {
  53.450 - 		if (skb_header_cloned(skb)) {
  53.451 - 			err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
  53.452 - 			if (err)
  53.453 -@@ -1171,7 +1171,7 @@ ixgb_tso(struct ixgb_adapter *adapter, s
  53.454 - 		}
  53.455 - 
  53.456 - 		hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
  53.457 --		mss = skb_shinfo(skb)->tso_size;
  53.458 -+		mss = skb_shinfo(skb)->gso_size;
  53.459 - 		skb->nh.iph->tot_len = 0;
  53.460 - 		skb->nh.iph->check = 0;
  53.461 - 		skb->h.th->check = ~csum_tcpudp_magic(skb->nh.iph->saddr,
  53.462 -diff -pruN ../orig-linux-2.6.16.29/drivers/net/loopback.c ./drivers/net/loopback.c
  53.463 ---- ../orig-linux-2.6.16.29/drivers/net/loopback.c	2006-09-12 19:02:10.000000000 +0100
  53.464 -+++ ./drivers/net/loopback.c	2006-09-19 13:59:20.000000000 +0100
  53.465 -@@ -74,7 +74,7 @@ static void emulate_large_send_offload(s
  53.466 - 	struct iphdr *iph = skb->nh.iph;
  53.467 - 	struct tcphdr *th = (struct tcphdr*)(skb->nh.raw + (iph->ihl * 4));
  53.468 - 	unsigned int doffset = (iph->ihl + th->doff) * 4;
  53.469 --	unsigned int mtu = skb_shinfo(skb)->tso_size + doffset;
  53.470 -+	unsigned int mtu = skb_shinfo(skb)->gso_size + doffset;
  53.471 - 	unsigned int offset = 0;
  53.472 - 	u32 seq = ntohl(th->seq);
  53.473 - 	u16 id  = ntohs(iph->id);
  53.474 -@@ -139,7 +139,7 @@ static int loopback_xmit(struct sk_buff 
  53.475 - #endif
  53.476 - 
  53.477 - #ifdef LOOPBACK_TSO
  53.478 --	if (skb_shinfo(skb)->tso_size) {
  53.479 -+	if (skb_shinfo(skb)->gso_size) {
  53.480 - 		BUG_ON(skb->protocol != htons(ETH_P_IP));
  53.481 - 		BUG_ON(skb->nh.iph->protocol != IPPROTO_TCP);
  53.482 - 
  53.483 -diff -pruN ../orig-linux-2.6.16.29/drivers/net/mv643xx_eth.c ./drivers/net/mv643xx_eth.c
  53.484 ---- ../orig-linux-2.6.16.29/drivers/net/mv643xx_eth.c	2006-09-12 19:02:10.000000000 +0100
  53.485 -+++ ./drivers/net/mv643xx_eth.c	2006-09-19 13:59:20.000000000 +0100
  53.486 -@@ -1107,7 +1107,7 @@ static int mv643xx_eth_start_xmit(struct
  53.487 - 
  53.488 - #ifdef MV643XX_CHECKSUM_OFFLOAD_TX
  53.489 - 	if (has_tiny_unaligned_frags(skb)) {
  53.490 --		if ((skb_linearize(skb, GFP_ATOMIC) != 0)) {
  53.491 -+		if (__skb_linearize(skb)) {
  53.492 - 			stats->tx_dropped++;
  53.493 - 			printk(KERN_DEBUG "%s: failed to linearize tiny "
  53.494 - 					"unaligned fragment\n", dev->name);
  53.495 -diff -pruN ../orig-linux-2.6.16.29/drivers/net/natsemi.c ./drivers/net/natsemi.c
  53.496 ---- ../orig-linux-2.6.16.29/drivers/net/natsemi.c	2006-09-12 19:02:10.000000000 +0100
  53.497 -+++ ./drivers/net/natsemi.c	2006-09-19 13:59:20.000000000 +0100
  53.498 -@@ -323,12 +323,12 @@ performance critical codepaths:
  53.499 - The rx process only runs in the interrupt handler. Access from outside
  53.500 - the interrupt handler is only permitted after disable_irq().
  53.501 - 
  53.502 --The rx process usually runs under the dev->xmit_lock. If np->intr_tx_reap
  53.503 -+The rx process usually runs under the netif_tx_lock. If np->intr_tx_reap
  53.504 - is set, then access is permitted under spin_lock_irq(&np->lock).
  53.505 - 
  53.506 - Thus configuration functions that want to access everything must call
  53.507 - 	disable_irq(dev->irq);
  53.508 --	spin_lock_bh(dev->xmit_lock);
  53.509 -+	netif_tx_lock_bh(dev);
  53.510 - 	spin_lock_irq(&np->lock);
  53.511 - 
  53.512 - IV. Notes
  53.513 -diff -pruN ../orig-linux-2.6.16.29/drivers/net/r8169.c ./drivers/net/r8169.c
  53.514 ---- ../orig-linux-2.6.16.29/drivers/net/r8169.c	2006-09-12 19:02:10.000000000 +0100
  53.515 -+++ ./drivers/net/r8169.c	2006-09-19 13:59:20.000000000 +0100
  53.516 -@@ -2171,7 +2171,7 @@ static int rtl8169_xmit_frags(struct rtl
  53.517 - static inline u32 rtl8169_tso_csum(struct sk_buff *skb, struct net_device *dev)
  53.518 - {
  53.519 - 	if (dev->features & NETIF_F_TSO) {
  53.520 --		u32 mss = skb_shinfo(skb)->tso_size;
  53.521 -+		u32 mss = skb_shinfo(skb)->gso_size;
  53.522 - 
  53.523 - 		if (mss)
  53.524 - 			return LargeSend | ((mss & MSSMask) << MSSShift);
  53.525 -diff -pruN ../orig-linux-2.6.16.29/drivers/net/s2io.c ./drivers/net/s2io.c
  53.526 ---- ../orig-linux-2.6.16.29/drivers/net/s2io.c	2006-09-12 19:02:10.000000000 +0100
  53.527 -+++ ./drivers/net/s2io.c	2006-09-19 13:59:20.000000000 +0100
  53.528 -@@ -3522,8 +3522,8 @@ static int s2io_xmit(struct sk_buff *skb
  53.529 - 	txdp->Control_1 = 0;
  53.530 - 	txdp->Control_2 = 0;
  53.531 - #ifdef NETIF_F_TSO
  53.532 --	mss = skb_shinfo(skb)->tso_size;
  53.533 --	if (mss) {
  53.534 -+	mss = skb_shinfo(skb)->gso_size;
  53.535 -+	if (skb_shinfo(skb)->gso_type == SKB_GSO_TCPV4) {
  53.536 - 		txdp->Control_1 |= TXD_TCP_LSO_EN;
  53.537 - 		txdp->Control_1 |= TXD_TCP_LSO_MSS(mss);
  53.538 - 	}
  53.539 -@@ -3543,10 +3543,10 @@ static int s2io_xmit(struct sk_buff *skb
  53.540 - 	}
  53.541 - 
  53.542 - 	frg_len = skb->len - skb->data_len;
  53.543 --	if (skb_shinfo(skb)->ufo_size) {
  53.544 -+	if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4) {
  53.545 - 		int ufo_size;
  53.546 - 
  53.547 --		ufo_size = skb_shinfo(skb)->ufo_size;
  53.548 -+		ufo_size = skb_shinfo(skb)->gso_size;
  53.549 - 		ufo_size &= ~7;
  53.550 - 		txdp->Control_1 |= TXD_UFO_EN;
  53.551 - 		txdp->Control_1 |= TXD_UFO_MSS(ufo_size);
  53.552 -@@ -3572,7 +3572,7 @@ static int s2io_xmit(struct sk_buff *skb
  53.553 - 	txdp->Host_Control = (unsigned long) skb;
  53.554 - 	txdp->Control_1 |= TXD_BUFFER0_SIZE(frg_len);
  53.555 - 
  53.556 --	if (skb_shinfo(skb)->ufo_size)
  53.557 -+	if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4)
  53.558 - 		txdp->Control_1 |= TXD_UFO_EN;
  53.559 - 
  53.560 - 	frg_cnt = skb_shinfo(skb)->nr_frags;
  53.561 -@@ -3587,12 +3587,12 @@ static int s2io_xmit(struct sk_buff *skb
  53.562 - 		    (sp->pdev, frag->page, frag->page_offset,
  53.563 - 		     frag->size, PCI_DMA_TODEVICE);
  53.564 - 		txdp->Control_1 = TXD_BUFFER0_SIZE(frag->size);
  53.565 --		if (skb_shinfo(skb)->ufo_size)
  53.566 -+		if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4)
  53.567 - 			txdp->Control_1 |= TXD_UFO_EN;
  53.568 - 	}
  53.569 - 	txdp->Control_1 |= TXD_GATHER_CODE_LAST;
  53.570 - 
  53.571 --	if (skb_shinfo(skb)->ufo_size)
  53.572 -+	if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4)
  53.573 - 		frg_cnt++; /* as Txd0 was used for inband header */
  53.574 - 
  53.575 - 	tx_fifo = mac_control->tx_FIFO_start[queue];
  53.576 -@@ -3606,7 +3606,7 @@ static int s2io_xmit(struct sk_buff *skb
  53.577 - 	if (mss)
  53.578 - 		val64 |= TX_FIFO_SPECIAL_FUNC;
  53.579 - #endif
  53.580 --	if (skb_shinfo(skb)->ufo_size)
  53.581 -+	if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4)
  53.582 - 		val64 |= TX_FIFO_SPECIAL_FUNC;
  53.583 - 	writeq(val64, &tx_fifo->List_Control);
  53.584 - 
  53.585 -diff -pruN ../orig-linux-2.6.16.29/drivers/net/sky2.c ./drivers/net/sky2.c
  53.586 ---- ../orig-linux-2.6.16.29/drivers/net/sky2.c	2006-09-12 19:02:10.000000000 +0100
  53.587 -+++ ./drivers/net/sky2.c	2006-09-19 13:59:20.000000000 +0100
  53.588 -@@ -1125,7 +1125,7 @@ static unsigned tx_le_req(const struct s
  53.589 - 	count = sizeof(dma_addr_t) / sizeof(u32);
  53.590 - 	count += skb_shinfo(skb)->nr_frags * count;
  53.591 - 
  53.592 --	if (skb_shinfo(skb)->tso_size)
  53.593 -+	if (skb_shinfo(skb)->gso_size)
  53.594 - 		++count;
  53.595 - 
  53.596 - 	if (skb->ip_summed == CHECKSUM_HW)
  53.597 -@@ -1197,7 +1197,7 @@ static int sky2_xmit_frame(struct sk_buf
  53.598 - 	}
  53.599 - 
  53.600 - 	/* Check for TCP Segmentation Offload */
  53.601 --	mss = skb_shinfo(skb)->tso_size;
  53.602 -+	mss = skb_shinfo(skb)->gso_size;
  53.603 - 	if (mss != 0) {
  53.604 - 		/* just drop the packet if non-linear expansion fails */
  53.605 - 		if (skb_header_cloned(skb) &&
  53.606 -diff -pruN ../orig-linux-2.6.16.29/drivers/net/tg3.c ./drivers/net/tg3.c
  53.607 ---- ../orig-linux-2.6.16.29/drivers/net/tg3.c	2006-09-12 19:02:10.000000000 +0100
  53.608 -+++ ./drivers/net/tg3.c	2006-09-19 13:59:20.000000000 +0100
  53.609 -@@ -3664,7 +3664,7 @@ static int tg3_start_xmit(struct sk_buff
  53.610 - #if TG3_TSO_SUPPORT != 0
  53.611 - 	mss = 0;
  53.612 - 	if (skb->len > (tp->dev->mtu + ETH_HLEN) &&
  53.613 --	    (mss = skb_shinfo(skb)->tso_size) != 0) {
  53.614 -+	    (mss = skb_shinfo(skb)->gso_size) != 0) {
  53.615 - 		int tcp_opt_len, ip_tcp_len;
  53.616 - 
  53.617 - 		if (skb_header_cloned(skb) &&
  53.618 -diff -pruN ../orig-linux-2.6.16.29/drivers/net/tulip/winbond-840.c ./drivers/net/tulip/winbond-840.c
  53.619 ---- ../orig-linux-2.6.16.29/drivers/net/tulip/winbond-840.c	2006-09-12 19:02:10.000000000 +0100
  53.620 -+++ ./drivers/net/tulip/winbond-840.c	2006-09-19 13:59:20.000000000 +0100
  53.621 -@@ -1605,11 +1605,11 @@ static void __devexit w840_remove1 (stru
  53.622 -  * - get_stats:
  53.623 -  * 	spin_lock_irq(np->lock), doesn't touch hw if not present
  53.624 -  * - hard_start_xmit:
  53.625 -- * 	netif_stop_queue + spin_unlock_wait(&dev->xmit_lock);
  53.626 -+ * 	synchronize_irq + netif_tx_disable;
  53.627 -  * - tx_timeout:
  53.628 -- * 	netif_device_detach + spin_unlock_wait(&dev->xmit_lock);
  53.629 -+ * 	netif_device_detach + netif_tx_disable;
  53.630 -  * - set_multicast_list
  53.631 -- * 	netif_device_detach + spin_unlock_wait(&dev->xmit_lock);
  53.632 -+ * 	netif_device_detach + netif_tx_disable;
  53.633 -  * - interrupt handler
  53.634 -  * 	doesn't touch hw if not present, synchronize_irq waits for
  53.635 -  * 	running instances of the interrupt handler.
  53.636 -@@ -1635,11 +1635,10 @@ static int w840_suspend (struct pci_dev 
  53.637 - 		netif_device_detach(dev);
  53.638 - 		update_csr6(dev, 0);
  53.639 - 		iowrite32(0, ioaddr + IntrEnable);
  53.640 --		netif_stop_queue(dev);
  53.641 - 		spin_unlock_irq(&np->lock);
  53.642 - 
  53.643 --		spin_unlock_wait(&dev->xmit_lock);
  53.644 - 		synchronize_irq(dev->irq);
  53.645 -+		netif_tx_disable(dev);
  53.646 - 	
  53.647 - 		np->stats.rx_missed_errors += ioread32(ioaddr + RxMissed) & 0xffff;
  53.648 - 
  53.649 -diff -pruN ../orig-linux-2.6.16.29/drivers/net/typhoon.c ./drivers/net/typhoon.c
  53.650 ---- ../orig-linux-2.6.16.29/drivers/net/typhoon.c	2006-09-12 19:02:10.000000000 +0100
  53.651 -+++ ./drivers/net/typhoon.c	2006-09-19 13:59:20.000000000 +0100
  53.652 -@@ -340,7 +340,7 @@ enum state_values {
  53.653 - #endif
  53.654 - 
  53.655 - #if defined(NETIF_F_TSO)
  53.656 --#define skb_tso_size(x)		(skb_shinfo(x)->tso_size)
  53.657 -+#define skb_tso_size(x)		(skb_shinfo(x)->gso_size)
  53.658 - #define TSO_NUM_DESCRIPTORS	2
  53.659 - #define TSO_OFFLOAD_ON		TYPHOON_OFFLOAD_TCP_SEGMENT
  53.660 - #else
  53.661 -diff -pruN ../orig-linux-2.6.16.29/drivers/net/via-velocity.c ./drivers/net/via-velocity.c
  53.662 ---- ../orig-linux-2.6.16.29/drivers/net/via-velocity.c	2006-09-12 19:02:10.000000000 +0100
  53.663 -+++ ./drivers/net/via-velocity.c	2006-09-19 13:59:20.000000000 +0100
  53.664 -@@ -1899,6 +1899,13 @@ static int velocity_xmit(struct sk_buff 
  53.665 - 
  53.666 - 	int pktlen = skb->len;
  53.667 - 
  53.668 -+#ifdef VELOCITY_ZERO_COPY_SUPPORT
  53.669 -+	if (skb_shinfo(skb)->nr_frags > 6 && __skb_linearize(skb)) {
  53.670 -+		kfree_skb(skb);
  53.671 -+		return 0;
  53.672 -+	}
  53.673 -+#endif
  53.674 -+
  53.675 - 	spin_lock_irqsave(&vptr->lock, flags);
  53.676 - 
  53.677 - 	index = vptr->td_curr[qnum];
  53.678 -@@ -1914,8 +1921,6 @@ static int velocity_xmit(struct sk_buff 
  53.679 - 	 */
  53.680 - 	if (pktlen < ETH_ZLEN) {
  53.681 - 		/* Cannot occur until ZC support */
  53.682 --		if(skb_linearize(skb, GFP_ATOMIC))
  53.683 --			return 0; 
  53.684 - 		pktlen = ETH_ZLEN;
  53.685 - 		memcpy(tdinfo->buf, skb->data, skb->len);
  53.686 - 		memset(tdinfo->buf + skb->len, 0, ETH_ZLEN - skb->len);
  53.687 -@@ -1933,7 +1938,6 @@ static int velocity_xmit(struct sk_buff 
  53.688 - 		int nfrags = skb_shinfo(skb)->nr_frags;
  53.689 - 		tdinfo->skb = skb;
  53.690 - 		if (nfrags > 6) {
  53.691 --			skb_linearize(skb, GFP_ATOMIC);
  53.692 - 			memcpy(tdinfo->buf, skb->data, skb->len);
  53.693 - 			tdinfo->skb_dma[0] = tdinfo->buf_dma;
  53.694 - 			td_ptr->tdesc0.pktsize = 
  53.695 -diff -pruN ../orig-linux-2.6.16.29/drivers/net/wireless/orinoco.c ./drivers/net/wireless/orinoco.c
  53.696 ---- ../orig-linux-2.6.16.29/drivers/net/wireless/orinoco.c	2006-09-12 19:02:10.000000000 +0100
  53.697 -+++ ./drivers/net/wireless/orinoco.c	2006-09-19 13:59:20.000000000 +0100
  53.698 -@@ -1835,7 +1835,9 @@ static int __orinoco_program_rids(struct
  53.699 - 	/* Set promiscuity / multicast*/
  53.700 - 	priv->promiscuous = 0;
  53.701 - 	priv->mc_count = 0;
  53.702 --	__orinoco_set_multicast_list(dev); /* FIXME: what about the xmit_lock */
  53.703 -+
  53.704 -+	/* FIXME: what about netif_tx_lock */
  53.705 -+	__orinoco_set_multicast_list(dev);
  53.706 - 
  53.707 - 	return 0;
  53.708 - }
  53.709 -diff -pruN ../orig-linux-2.6.16.29/drivers/s390/net/qeth_eddp.c ./drivers/s390/net/qeth_eddp.c
  53.710 ---- ../orig-linux-2.6.16.29/drivers/s390/net/qeth_eddp.c	2006-09-12 19:02:10.000000000 +0100
  53.711 -+++ ./drivers/s390/net/qeth_eddp.c	2006-09-19 13:59:20.000000000 +0100
  53.712 -@@ -421,7 +421,7 @@ __qeth_eddp_fill_context_tcp(struct qeth
  53.713 -        }
  53.714 - 	tcph = eddp->skb->h.th;
  53.715 - 	while (eddp->skb_offset < eddp->skb->len) {
  53.716 --		data_len = min((int)skb_shinfo(eddp->skb)->tso_size,
  53.717 -+		data_len = min((int)skb_shinfo(eddp->skb)->gso_size,
  53.718 - 			       (int)(eddp->skb->len - eddp->skb_offset));
  53.719 - 		/* prepare qdio hdr */
  53.720 - 		if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2){
  53.721 -@@ -516,20 +516,20 @@ qeth_eddp_calc_num_pages(struct qeth_edd
  53.722 - 	
  53.723 - 	QETH_DBF_TEXT(trace, 5, "eddpcanp");
  53.724 - 	/* can we put multiple skbs in one page? */
  53.725 --	skbs_per_page = PAGE_SIZE / (skb_shinfo(skb)->tso_size + hdr_len);
  53.726 -+	skbs_per_page = PAGE_SIZE / (skb_shinfo(skb)->gso_size + hdr_len);
  53.727 - 	if (skbs_per_page > 1){
  53.728 --		ctx->num_pages = (skb_shinfo(skb)->tso_segs + 1) /
  53.729 -+		ctx->num_pages = (skb_shinfo(skb)->gso_segs + 1) /
  53.730 - 				 skbs_per_page + 1;
  53.731 - 		ctx->elements_per_skb = 1;
  53.732 - 	} else {
  53.733 - 		/* no -> how many elements per skb? */
  53.734 --		ctx->elements_per_skb = (skb_shinfo(skb)->tso_size + hdr_len +
  53.735 -+		ctx->elements_per_skb = (skb_shinfo(skb)->gso_size + hdr_len +
  53.736 - 				     PAGE_SIZE) >> PAGE_SHIFT;
  53.737 - 		ctx->num_pages = ctx->elements_per_skb *
  53.738 --				 (skb_shinfo(skb)->tso_segs + 1);
  53.739 -+				 (skb_shinfo(skb)->gso_segs + 1);
  53.740 - 	}
  53.741 - 	ctx->num_elements = ctx->elements_per_skb *
  53.742 --			    (skb_shinfo(skb)->tso_segs + 1);
  53.743 -+			    (skb_shinfo(skb)->gso_segs + 1);
  53.744 - }
  53.745 - 
  53.746 - static inline struct qeth_eddp_context *
  53.747 -diff -pruN ../orig-linux-2.6.16.29/drivers/s390/net/qeth_main.c ./drivers/s390/net/qeth_main.c
  53.748 ---- ../orig-linux-2.6.16.29/drivers/s390/net/qeth_main.c	2006-09-12 19:02:10.000000000 +0100
  53.749 -+++ ./drivers/s390/net/qeth_main.c	2006-09-19 13:59:20.000000000 +0100
  53.750 -@@ -4454,7 +4454,7 @@ qeth_send_packet(struct qeth_card *card,
  53.751 - 	queue = card->qdio.out_qs
  53.752 - 		[qeth_get_priority_queue(card, skb, ipv, cast_type)];
  53.753 - 
  53.754 --	if (skb_shinfo(skb)->tso_size)
  53.755 -+	if (skb_shinfo(skb)->gso_size)
  53.756 - 		large_send = card->options.large_send;
  53.757 - 
  53.758 - 	/*are we able to do TSO ? If so ,prepare and send it from here */
  53.759 -@@ -4501,7 +4501,7 @@ qeth_send_packet(struct qeth_card *card,
  53.760 - 		card->stats.tx_packets++;
  53.761 - 		card->stats.tx_bytes += skb->len;
  53.762 - #ifdef CONFIG_QETH_PERF_STATS
  53.763 --		if (skb_shinfo(skb)->tso_size &&
  53.764 -+		if (skb_shinfo(skb)->gso_size &&
  53.765 - 		   !(large_send == QETH_LARGE_SEND_NO)) {
  53.766 - 			card->perf_stats.large_send_bytes += skb->len;
  53.767 - 			card->perf_stats.large_send_cnt++;
  53.768 -diff -pruN ../orig-linux-2.6.16.29/drivers/s390/net/qeth_tso.h ./drivers/s390/net/qeth_tso.h
  53.769 ---- ../orig-linux-2.6.16.29/drivers/s390/net/qeth_tso.h	2006-09-12 19:02:10.000000000 +0100
  53.770 -+++ ./drivers/s390/net/qeth_tso.h	2006-09-19 13:59:20.000000000 +0100
  53.771 -@@ -51,7 +51,7 @@ qeth_tso_fill_header(struct qeth_card *c
  53.772 - 	hdr->ext.hdr_version = 1;
  53.773 - 	hdr->ext.hdr_len     = 28;
  53.774 - 	/*insert non-fix values */
  53.775 --	hdr->ext.mss = skb_shinfo(skb)->tso_size;
  53.776 -+	hdr->ext.mss = skb_shinfo(skb)->gso_size;
  53.777 - 	hdr->ext.dg_hdr_len = (__u16)(iph->ihl*4 + tcph->doff*4);
  53.778 - 	hdr->ext.payload_len = (__u16)(skb->len - hdr->ext.dg_hdr_len -
  53.779 - 				       sizeof(struct qeth_hdr_tso));
  53.780 -diff -pruN ../orig-linux-2.6.16.29/include/linux/ethtool.h ./include/linux/ethtool.h
  53.781 ---- ../orig-linux-2.6.16.29/include/linux/ethtool.h	2006-09-12 19:02:10.000000000 +0100
  53.782 -+++ ./include/linux/ethtool.h	2006-09-19 13:59:20.000000000 +0100
  53.783 -@@ -408,6 +408,8 @@ struct ethtool_ops {
  53.784 - #define ETHTOOL_GPERMADDR	0x00000020 /* Get permanent hardware address */
  53.785 - #define ETHTOOL_GUFO		0x00000021 /* Get UFO enable (ethtool_value) */
  53.786 - #define ETHTOOL_SUFO		0x00000022 /* Set UFO enable (ethtool_value) */
  53.787 -+#define ETHTOOL_GGSO		0x00000023 /* Get GSO enable (ethtool_value) */
  53.788 -+#define ETHTOOL_SGSO		0x00000024 /* Set GSO enable (ethtool_value) */
  53.789 - 
  53.790 - /* compatibility with older code */
  53.791 - #define SPARC_ETH_GSET		ETHTOOL_GSET
  53.792 -diff -pruN ../orig-linux-2.6.16.29/include/linux/netdevice.h ./include/linux/netdevice.h
  53.793 ---- ../orig-linux-2.6.16.29/include/linux/netdevice.h	2006-09-12 19:02:10.000000000 +0100
  53.794 -+++ ./include/linux/netdevice.h	2006-09-19 13:59:20.000000000 +0100
  53.795 -@@ -230,7 +230,8 @@ enum netdev_state_t
  53.796 - 	__LINK_STATE_SCHED,
  53.797 - 	__LINK_STATE_NOCARRIER,
  53.798 - 	__LINK_STATE_RX_SCHED,
  53.799 --	__LINK_STATE_LINKWATCH_PENDING
  53.800 -+	__LINK_STATE_LINKWATCH_PENDING,
  53.801 -+	__LINK_STATE_QDISC_RUNNING,
  53.802 - };
  53.803 - 
  53.804 - 
  53.805 -@@ -306,9 +307,17 @@ struct net_device
  53.806 - #define NETIF_F_HW_VLAN_RX	256	/* Receive VLAN hw acceleration */
  53.807 - #define NETIF_F_HW_VLAN_FILTER	512	/* Receive filtering on VLAN */
  53.808 - #define NETIF_F_VLAN_CHALLENGED	1024	/* Device cannot handle VLAN packets */
  53.809 --#define NETIF_F_TSO		2048	/* Can offload TCP/IP segmentation */
  53.810 -+#define NETIF_F_GSO		2048	/* Enable software GSO. */
  53.811 - #define NETIF_F_LLTX		4096	/* LockLess TX */
  53.812 --#define NETIF_F_UFO             8192    /* Can offload UDP Large Send*/
  53.813 -+
  53.814 -+	/* Segmentation offload features */
  53.815 -+#define NETIF_F_GSO_SHIFT	16
  53.816 -+#define NETIF_F_TSO		(SKB_GSO_TCPV4 << NETIF_F_GSO_SHIFT)
  53.817 -+#define NETIF_F_UFO		(SKB_GSO_UDPV4 << NETIF_F_GSO_SHIFT)
  53.818 -+#define NETIF_F_GSO_ROBUST	(SKB_GSO_DODGY << NETIF_F_GSO_SHIFT)
  53.819 -+
  53.820 -+#define NETIF_F_GEN_CSUM	(NETIF_F_NO_CSUM | NETIF_F_HW_CSUM)
  53.821 -+#define NETIF_F_ALL_CSUM	(NETIF_F_IP_CSUM | NETIF_F_GEN_CSUM)
  53.822 - 
  53.823 - 	struct net_device	*next_sched;
  53.824 - 
  53.825 -@@ -394,6 +403,9 @@ struct net_device
  53.826 - 	struct list_head	qdisc_list;
  53.827 - 	unsigned long		tx_queue_len;	/* Max frames per queue allowed */
  53.828 - 
  53.829 -+	/* Partially transmitted GSO packet. */
  53.830 -+	struct sk_buff		*gso_skb;
  53.831 -+
  53.832 - 	/* ingress path synchronizer */
  53.833 - 	spinlock_t		ingress_lock;
  53.834 - 	struct Qdisc		*qdisc_ingress;
  53.835 -@@ -402,7 +414,7 @@ struct net_device
  53.836 -  * One part is mostly used on xmit path (device)
  53.837 -  */
  53.838 - 	/* hard_start_xmit synchronizer */
  53.839 --	spinlock_t		xmit_lock ____cacheline_aligned_in_smp;
  53.840 -+	spinlock_t		_xmit_lock ____cacheline_aligned_in_smp;
  53.841 - 	/* cpu id of processor entered to hard_start_xmit or -1,
  53.842 - 	   if nobody entered there.
  53.843 - 	 */
  53.844 -@@ -527,6 +539,8 @@ struct packet_type {
  53.845 - 					 struct net_device *,
  53.846 - 					 struct packet_type *,
  53.847 - 					 struct net_device *);
  53.848 -+	struct sk_buff		*(*gso_segment)(struct sk_buff *skb,
  53.849 -+						int features);
  53.850 - 	void			*af_packet_priv;
  53.851 - 	struct list_head	list;
  53.852 - };
  53.853 -@@ -693,7 +707,8 @@ extern int		dev_change_name(struct net_d
  53.854 - extern int		dev_set_mtu(struct net_device *, int);
  53.855 - extern int		dev_set_mac_address(struct net_device *,
  53.856 - 					    struct sockaddr *);
  53.857 --extern void		dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev);
  53.858 -+extern int		dev_hard_start_xmit(struct sk_buff *skb,
  53.859 -+					    struct net_device *dev);
  53.860 - 
  53.861 - extern void		dev_init(void);
  53.862 - 
  53.863 -@@ -900,11 +915,43 @@ static inline void __netif_rx_complete(s
  53.864 - 	clear_bit(__LINK_STATE_RX_SCHED, &dev->state);
  53.865 - }
  53.866 - 
  53.867 -+static inline void netif_tx_lock(struct net_device *dev)
  53.868 -+{
  53.869 -+	spin_lock(&dev->_xmit_lock);
  53.870 -+	dev->xmit_lock_owner = smp_processor_id();
  53.871 -+}
  53.872 -+
  53.873 -+static inline void netif_tx_lock_bh(struct net_device *dev)
  53.874 -+{
  53.875 -+	spin_lock_bh(&dev->_xmit_lock);
  53.876 -+	dev->xmit_lock_owner = smp_processor_id();
  53.877 -+}
  53.878 -+
  53.879 -+static inline int netif_tx_trylock(struct net_device *dev)
  53.880 -+{
  53.881 -+	int err = spin_trylock(&dev->_xmit_lock);
  53.882 -+	if (!err)
  53.883 -+		dev->xmit_lock_owner = smp_processor_id();
  53.884 -+	return err;
  53.885 -+}
  53.886 -+
  53.887 -+static inline void netif_tx_unlock(struct net_device *dev)
  53.888 -+{
  53.889 -+	dev->xmit_lock_owner = -1;
  53.890 -+	spin_unlock(&dev->_xmit_lock);
  53.891 -+}
  53.892 -+
  53.893 -+static inline void netif_tx_unlock_bh(struct net_device *dev)
  53.894 -+{
  53.895 -+	dev->xmit_lock_owner = -1;
  53.896 -+	spin_unlock_bh(&dev->_xmit_lock);
  53.897 -+}
  53.898 -+
  53.899 - static inline void netif_tx_disable(struct net_device *dev)
  53.900 - {
  53.901 --	spin_lock_bh(&dev->xmit_lock);
  53.902 -+	netif_tx_lock_bh(dev);
  53.903 - 	netif_stop_queue(dev);
  53.904 --	spin_unlock_bh(&dev->xmit_lock);
  53.905 -+	netif_tx_unlock_bh(dev);
  53.906 - }
  53.907 - 
  53.908 - /* These functions live elsewhere (drivers/net/net_init.c, but related) */
  53.909 -@@ -932,6 +979,7 @@ extern int		netdev_max_backlog;
  53.910 - extern int		weight_p;
  53.911 - extern int		netdev_set_master(struct net_device *dev, struct net_device *master);
  53.912 - extern int skb_checksum_help(struct sk_buff *skb, int inward);
  53.913 -+extern struct sk_buff *skb_gso_segment(struct sk_buff *skb, int features);
  53.914 - #ifdef CONFIG_BUG
  53.915 - extern void netdev_rx_csum_fault(struct net_device *dev);
  53.916 - #else
  53.917 -@@ -951,6 +999,18 @@ extern void dev_seq_stop(struct seq_file
  53.918 - 
  53.919 - extern void linkwatch_run_queue(void);
  53.920 - 
  53.921 -+static inline int skb_gso_ok(struct sk_buff *skb, int features)
  53.922 -+{
  53.923 -+	int feature = skb_shinfo(skb)->gso_size ?
  53.924 -+		      skb_shinfo(skb)->gso_type << NETIF_F_GSO_SHIFT : 0;
  53.925 -+	return (features & feature) == feature;
  53.926 -+}
  53.927 -+
  53.928 -+static inline int netif_needs_gso(struct net_device *dev, struct sk_buff *skb)
  53.929 -+{
  53.930 -+	return !skb_gso_ok(skb, dev->features);
  53.931 -+}
  53.932 -+
  53.933 - #endif /* __KERNEL__ */
  53.934 - 
  53.935 - #endif	/* _LINUX_DEV_H */
  53.936 -diff -pruN ../orig-linux-2.6.16.29/include/linux/skbuff.h ./include/linux/skbuff.h
  53.937 ---- ../orig-linux-2.6.16.29/include/linux/skbuff.h	2006-09-12 19:02:10.000000000 +0100
  53.938 -+++ ./include/linux/skbuff.h	2006-09-19 13:59:20.000000000 +0100
  53.939 -@@ -134,9 +134,10 @@ struct skb_frag_struct {
  53.940 - struct skb_shared_info {
  53.941 - 	atomic_t	dataref;
  53.942 - 	unsigned short	nr_frags;
  53.943 --	unsigned short	tso_size;
  53.944 --	unsigned short	tso_segs;
  53.945 --	unsigned short  ufo_size;
  53.946 -+	unsigned short	gso_size;
  53.947 -+	/* Warning: this field is not always filled in (UFO)! */
  53.948 -+	unsigned short	gso_segs;
  53.949 -+	unsigned short  gso_type;
  53.950 - 	unsigned int    ip6_frag_id;
  53.951 - 	struct sk_buff	*frag_list;
  53.952 - 	skb_frag_t	frags[MAX_SKB_FRAGS];
  53.953 -@@ -168,6 +169,14 @@ enum {
  53.954 - 	SKB_FCLONE_CLONE,
  53.955 - };
  53.956 - 
  53.957 -+enum {
  53.958 -+	SKB_GSO_TCPV4 = 1 << 0,
  53.959 -+	SKB_GSO_UDPV4 = 1 << 1,
  53.960 -+
  53.961 -+	/* This indicates the skb is from an untrusted source. */
  53.962 -+	SKB_GSO_DODGY = 1 << 2,
  53.963 -+};
  53.964 -+
  53.965 - /** 
  53.966 -  *	struct sk_buff - socket buffer
  53.967 -  *	@next: Next buffer in list
  53.968 -@@ -1148,18 +1157,34 @@ static inline int skb_can_coalesce(struc
  53.969 - 	return 0;
  53.970 - }
  53.971 - 
  53.972 -+static inline int __skb_linearize(struct sk_buff *skb)
  53.973 -+{
  53.974 -+	return __pskb_pull_tail(skb, skb->data_len) ? 0 : -ENOMEM;
  53.975 -+}
  53.976 -+
  53.977 - /**
  53.978 -  *	skb_linearize - convert paged skb to linear one
  53.979 -  *	@skb: buffer to linarize
  53.980 -- *	@gfp: allocation mode
  53.981 -  *
  53.982 -  *	If there is no free memory -ENOMEM is returned, otherwise zero
  53.983 -  *	is returned and the old skb data released.
  53.984 -  */
  53.985 --extern int __skb_linearize(struct sk_buff *skb, gfp_t gfp);
  53.986 --static inline int skb_linearize(struct sk_buff *skb, gfp_t gfp)
  53.987 -+static inline int skb_linearize(struct sk_buff *skb)
  53.988 -+{
  53.989 -+	return skb_is_nonlinear(skb) ? __skb_linearize(skb) : 0;
  53.990 -+}
  53.991 -+
  53.992 -+/**
  53.993 -+ *	skb_linearize_cow - make sure skb is linear and writable
  53.994 -+ *	@skb: buffer to process
  53.995 -+ *
  53.996 -+ *	If there is no free memory -ENOMEM is returned, otherwise zero
  53.997 -+ *	is returned and the old skb data released.
  53.998 -+ */
  53.999 -+static inline int skb_linearize_cow(struct sk_buff *skb)
 53.1000 - {
 53.1001 --	return __skb_linearize(skb, gfp);
 53.1002 -+	return skb_is_nonlinear(skb) || skb_cloned(skb) ?
 53.1003 -+	       __skb_linearize(skb) : 0;
 53.1004 - }
 53.1005 - 
 53.1006 - /**
 53.1007 -@@ -1254,6 +1279,7 @@ extern void	       skb_split(struct sk_b
 53.1008 - 				 struct sk_buff *skb1, const u32 len);
 53.1009 - 
 53.1010 - extern void	       skb_release_data(struct sk_buff *skb);
 53.1011 -+extern struct sk_buff *skb_segment(struct sk_buff *skb, int features);
 53.1012 - 
 53.1013 - static inline void *skb_header_pointer(const struct sk_buff *skb, int offset,
 53.1014 - 				       int len, void *buffer)
 53.1015 -diff -pruN ../orig-linux-2.6.16.29/include/net/pkt_sched.h ./include/net/pkt_sched.h
 53.1016 ---- ../orig-linux-2.6.16.29/include/net/pkt_sched.h	2006-09-12 19:02:10.000000000 +0100
 53.1017 -+++ ./include/net/pkt_sched.h	2006-09-19 13:59:20.000000000 +0100
 53.1018 -@@ -218,12 +218,13 @@ extern struct qdisc_rate_table *qdisc_ge
 53.1019 - 		struct rtattr *tab);
 53.1020 - extern void qdisc_put_rtab(struct qdisc_rate_table *tab);
 53.1021 - 
 53.1022 --extern int qdisc_restart(struct net_device *dev);
 53.1023 -+extern void __qdisc_run(struct net_device *dev);
 53.1024 - 
 53.1025 - static inline void qdisc_run(struct net_device *dev)
 53.1026 - {
 53.1027 --	while (!netif_queue_stopped(dev) && qdisc_restart(dev) < 0)
 53.1028 --		/* NOTHING */;
 53.1029 -+	if (!netif_queue_stopped(dev) &&
 53.1030 -+	    !test_and_set_bit(__LINK_STATE_QDISC_RUNNING, &dev->state))
 53.1031 -+		__qdisc_run(dev);
 53.1032 - }
 53.1033 - 
 53.1034 - extern int tc_classify(struct sk_buff *skb, struct tcf_proto *tp,
 53.1035 -diff -pruN ../orig-linux-2.6.16.29/include/net/protocol.h ./include/net/protocol.h
 53.1036 ---- ../orig-linux-2.6.16.29/include/net/protocol.h	2006-09-12 19:02:10.000000000 +0100
 53.1037 -+++ ./include/net/protocol.h	2006-09-19 13:59:20.000000000 +0100
 53.1038 -@@ -37,6 +37,8 @@
 53.1039 - struct net_protocol {
 53.1040 - 	int			(*handler)(struct sk_buff *skb);
 53.1041 - 	void			(*err_handler)(struct sk_buff *skb, u32 info);
 53.1042 -+	struct sk_buff	       *(*gso_segment)(struct sk_buff *skb,
 53.1043 -+					       int features);
 53.1044 - 	int			no_policy;
 53.1045 - };
 53.1046 - 
 53.1047 -diff -pruN ../orig-linux-2.6.16.29/include/net/sock.h ./include/net/sock.h
 53.1048 ---- ../orig-linux-2.6.16.29/include/net/sock.h	2006-09-12 19:02:10.000000000 +0100
 53.1049 -+++ ./include/net/sock.h	2006-09-19 13:59:20.000000000 +0100
 53.1050 -@@ -1064,9 +1064,13 @@ static inline void sk_setup_caps(struct 
 53.1051 - {
 53.1052 - 	__sk_dst_set(sk, dst);
 53.1053 - 	sk->sk_route_caps = dst->dev->features;
 53.1054 -+	if (sk->sk_route_caps & NETIF_F_GSO)
 53.1055 -+		sk->sk_route_caps |= NETIF_F_TSO;
 53.1056 - 	if (sk->sk_route_caps & NETIF_F_TSO) {
 53.1057 - 		if (sock_flag(sk, SOCK_NO_LARGESEND) || dst->header_len)
 53.1058 - 			sk->sk_route_caps &= ~NETIF_F_TSO;
 53.1059 -+		else 
 53.1060 -+			sk->sk_route_caps |= NETIF_F_SG | NETIF_F_HW_CSUM;
 53.1061 - 	}
 53.1062 - }
 53.1063 - 
 53.1064 -diff -pruN ../orig-linux-2.6.16.29/include/net/tcp.h ./include/net/tcp.h
 53.1065 ---- ../orig-linux-2.6.16.29/include/net/tcp.h	2006-09-12 19:02:10.000000000 +0100
 53.1066 -+++ ./include/net/tcp.h	2006-09-19 13:59:20.000000000 +0100
 53.1067 -@@ -552,13 +552,13 @@ struct tcp_skb_cb {
 53.1068 -  */
 53.1069 - static inline int tcp_skb_pcount(const struct sk_buff *skb)
 53.1070 - {
 53.1071 --	return skb_shinfo(skb)->tso_segs;
 53.1072 -+	return skb_shinfo(skb)->gso_segs;
 53.1073 - }
 53.1074 - 
 53.1075 - /* This is valid iff tcp_skb_pcount() > 1. */
 53.1076 - static inline int tcp_skb_mss(const struct sk_buff *skb)
 53.1077 - {
 53.1078 --	return skb_shinfo(skb)->tso_size;
 53.1079 -+	return skb_shinfo(skb)->gso_size;
 53.1080 - }
 53.1081 - 
 53.1082 - static inline void tcp_dec_pcount_approx(__u32 *count,
 53.1083 -@@ -1063,6 +1063,8 @@ extern struct request_sock_ops tcp_reque
 53.1084 - 
 53.1085 - extern int tcp_v4_destroy_sock(struct sock *sk);
 53.1086 - 
 53.1087 -+extern struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features);
 53.1088 -+
 53.1089 - #ifdef CONFIG_PROC_FS
 53.1090 - extern int  tcp4_proc_init(void);
 53.1091 - extern void tcp4_proc_exit(void);
 53.1092 -diff -pruN ../orig-linux-2.6.16.29/net/atm/clip.c ./net/atm/clip.c
 53.1093 ---- ../orig-linux-2.6.16.29/net/atm/clip.c	2006-09-12 19:02:10.000000000 +0100
 53.1094 -+++ ./net/atm/clip.c	2006-09-19 13:59:20.000000000 +0100
 53.1095 -@@ -101,7 +101,7 @@ static void unlink_clip_vcc(struct clip_
 53.1096 - 		printk(KERN_CRIT "!clip_vcc->entry (clip_vcc %p)\n",clip_vcc);
 53.1097 - 		return;
 53.1098 - 	}
 53.1099 --	spin_lock_bh(&entry->neigh->dev->xmit_lock);	/* block clip_start_xmit() */
 53.1100 -+	netif_tx_lock_bh(entry->neigh->dev);	/* block clip_start_xmit() */
 53.1101 - 	entry->neigh->used = jiffies;
 53.1102 - 	for (walk = &entry->vccs; *walk; walk = &(*walk)->next)
 53.1103 - 		if (*walk == clip_vcc) {
 53.1104 -@@ -125,7 +125,7 @@ static void unlink_clip_vcc(struct clip_
 53.1105 - 	printk(KERN_CRIT "ATMARP: unlink_clip_vcc failed (entry %p, vcc "
 53.1106 - 	  "0x%p)\n",entry,clip_vcc);
 53.1107 - out:
 53.1108 --	spin_unlock_bh(&entry->neigh->dev->xmit_lock);
 53.1109 -+	netif_tx_unlock_bh(entry->neigh->dev);
 53.1110 - }
 53.1111 - 
 53.1112 - /* The neighbour entry n->lock is held. */
 53.1113 -diff -pruN ../orig-linux-2.6.16.29/net/bridge/br_device.c ./net/bridge/br_device.c
 53.1114 ---- ../orig-linux-2.6.16.29/net/bridge/br_device.c	2006-09-12 19:02:10.000000000 +0100
 53.1115 -+++ ./net/bridge/br_device.c	2006-09-19 13:59:20.000000000 +0100
 53.1116 -@@ -146,9 +146,9 @@ static int br_set_tx_csum(struct net_dev
 53.1117 - 	struct net_bridge *br = netdev_priv(dev);
 53.1118 - 
 53.1119 - 	if (data)
 53.1120 --		br->feature_mask |= NETIF_F_IP_CSUM;
 53.1121 -+		br->feature_mask |= NETIF_F_NO_CSUM;
 53.1122 - 	else
 53.1123 --		br->feature_mask &= ~NETIF_F_IP_CSUM;
 53.1124 -+		br->feature_mask &= ~NETIF_F_ALL_CSUM;
 53.1125 - 
 53.1126 - 	br_features_recompute(br);
 53.1127 - 	return 0;
 53.1128 -@@ -185,6 +185,6 @@ void br_dev_setup(struct net_device *dev
 53.1129 - 	dev->set_mac_address = br_set_mac_address;
 53.1130 - 	dev->priv_flags = IFF_EBRIDGE;
 53.1131 - 
 53.1132 -- 	dev->features = NETIF_F_SG | NETIF_F_FRAGLIST
 53.1133 -- 		| NETIF_F_HIGHDMA | NETIF_F_TSO | NETIF_F_IP_CSUM;
 53.1134 -+ 	dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA |
 53.1135 -+ 			NETIF_F_TSO | NETIF_F_NO_CSUM | NETIF_F_GSO_ROBUST;
 53.1136 - }
 53.1137 -diff -pruN ../orig-linux-2.6.16.29/net/bridge/br_forward.c ./net/bridge/br_forward.c
 53.1138 ---- ../orig-linux-2.6.16.29/net/bridge/br_forward.c	2006-09-12 19:02:10.000000000 +0100
 53.1139 -+++ ./net/bridge/br_forward.c	2006-09-19 13:59:20.000000000 +0100
 53.1140 -@@ -32,7 +32,7 @@ static inline int should_deliver(const s
 53.1141 - int br_dev_queue_push_xmit(struct sk_buff *skb)
 53.1142 - {
 53.1143 - 	/* drop mtu oversized packets except tso */
 53.1144 --	if (skb->len > skb->dev->mtu && !skb_shinfo(skb)->tso_size)
 53.1145 -+	if (skb->len > skb->dev->mtu && !skb_shinfo(skb)->gso_size)
 53.1146 - 		kfree_skb(skb);
 53.1147 - 	else {
 53.1148 - #ifdef CONFIG_BRIDGE_NETFILTER
 53.1149 -diff -pruN ../orig-linux-2.6.16.29/net/bridge/br_if.c ./net/bridge/br_if.c
 53.1150 ---- ../orig-linux-2.6.16.29/net/bridge/br_if.c	2006-09-12 19:02:10.000000000 +0100
 53.1151 -+++ ./net/bridge/br_if.c	2006-09-19 13:59:20.000000000 +0100
 53.1152 -@@ -385,17 +385,28 @@ void br_features_recompute(struct net_br
 53.1153 - 	struct net_bridge_port *p;
 53.1154 - 	unsigned long features, checksum;
 53.1155 - 
 53.1156 --	features = br->feature_mask &~ NETIF_F_IP_CSUM;
 53.1157 --	checksum = br->feature_mask & NETIF_F_IP_CSUM;
 53.1158 -+	checksum = br->feature_mask & NETIF_F_ALL_CSUM ? NETIF_F_NO_CSUM : 0;
 53.1159 -+	features = br->feature_mask & ~NETIF_F_ALL_CSUM;
 53.1160 - 
 53.1161 - 	list_for_each_entry(p, &br->port_list, list) {
 53.1162 --		if (!(p->dev->features 
 53.1163 --		      & (NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM)))
 53.1164 -+		unsigned long feature = p->dev->features;
 53.1165 -+
 53.1166 -+		if (checksum & NETIF_F_NO_CSUM && !(feature & NETIF_F_NO_CSUM))
 53.1167 -+			checksum ^= NETIF_F_NO_CSUM | NETIF_F_HW_CSUM;
 53.1168 -+		if (checksum & NETIF_F_HW_CSUM && !(feature & NETIF_F_HW_CSUM))
 53.1169 -+			checksum ^= NETIF_F_HW_CSUM | NETIF_F_IP_CSUM;
 53.1170 -+		if (!(feature & NETIF_F_IP_CSUM))
 53.1171 - 			checksum = 0;
 53.1172 --		features &= p->dev->features;
 53.1173 -+
 53.1174 -+		if (feature & NETIF_F_GSO)
 53.1175 -+			feature |= NETIF_F_TSO;
 53.1176 -+		feature |= NETIF_F_GSO;
 53.1177 -+
 53.1178 -+		features &= feature;
 53.1179 - 	}
 53.1180 - 
 53.1181 --	br->dev->features = features | checksum | NETIF_F_LLTX;
 53.1182 -+	br->dev->features = features | checksum | NETIF_F_LLTX |
 53.1183 -+			    NETIF_F_GSO_ROBUST;
 53.1184 - }
 53.1185 - 
 53.1186 - /* called with RTNL */
 53.1187 -diff -pruN ../orig-linux-2.6.16.29/net/bridge/br_netfilter.c ./net/bridge/br_netfilter.c
 53.1188 ---- ../orig-linux-2.6.16.29/net/bridge/br_netfilter.c	2006-09-12 19:02:10.000000000 +0100
 53.1189 -+++ ./net/bridge/br_netfilter.c	2006-09-19 13:59:20.000000000 +0100
 53.1190 -@@ -743,7 +743,7 @@ static int br_nf_dev_queue_xmit(struct s
 53.1191 - {
 53.1192 - 	if (skb->protocol == htons(ETH_P_IP) &&
 53.1193 - 	    skb->len > skb->dev->mtu &&
 53.1194 --	    !(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size))
 53.1195 -+	    !skb_shinfo(skb)->gso_size)
 53.1196 - 		return ip_fragment(skb, br_dev_queue_push_xmit);
 53.1197 - 	else
 53.1198 - 		return br_dev_queue_push_xmit(skb);
 53.1199 -diff -pruN ../orig-linux-2.6.16.29/net/core/dev.c ./net/core/dev.c
 53.1200 ---- ../orig-linux-2.6.16.29/net/core/dev.c	2006-09-12 19:02:10.000000000 +0100
 53.1201 -+++ ./net/core/dev.c	2006-09-19 13:59:20.000000000 +0100
 53.1202 -@@ -115,6 +115,7 @@
 53.1203 - #include <net/iw_handler.h>
 53.1204 - #endif	/* CONFIG_NET_RADIO */
 53.1205 - #include <asm/current.h>
 53.1206 -+#include <linux/err.h>
 53.1207 - 
 53.1208 - /*
 53.1209 -  *	The list of packet types we will receive (as opposed to discard)
 53.1210 -@@ -1032,7 +1033,7 @@ static inline void net_timestamp(struct 
 53.1211 -  *	taps currently in use.
 53.1212 -  */
 53.1213 - 
 53.1214 --void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
 53.1215 -+static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
 53.1216 - {
 53.1217 - 	struct packet_type *ptype;
 53.1218 - 
 53.1219 -@@ -1106,6 +1107,45 @@ out:	
 53.1220 - 	return ret;
 53.1221 - }
 53.1222 - 
 53.1223 -+/**
 53.1224 -+ *	skb_gso_segment - Perform segmentation on skb.
 53.1225 -+ *	@skb: buffer to segment
 53.1226 -+ *	@features: features for the output path (see dev->features)
 53.1227 -+ *
 53.1228 -+ *	This function segments the given skb and returns a list of segments.
 53.1229 -+ *
 53.1230 -+ *	It may return NULL if the skb requires no segmentation.  This is
 53.1231 -+ *	only possible when GSO is used for verifying header integrity.
 53.1232 -+ */
 53.1233 -+struct sk_buff *skb_gso_segment(struct sk_buff *skb, int features)
 53.1234 -+{
 53.1235 -+	struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT);
 53.1236 -+	struct packet_type *ptype;
 53.1237 -+	int type = skb->protocol;
 53.1238 -+
 53.1239 -+	BUG_ON(skb_shinfo(skb)->frag_list);
 53.1240 -+	BUG_ON(skb->ip_summed != CHECKSUM_HW);
 53.1241 -+
 53.1242 -+	skb->mac.raw = skb->data;
 53.1243 -+	skb->mac_len = skb->nh.raw - skb->data;
 53.1244 -+	__skb_pull(skb, skb->mac_len);
 53.1245 -+
 53.1246 -+	rcu_read_lock();
 53.1247 -+	list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type) & 15], list) {
 53.1248 -+		if (ptype->type == type && !ptype->dev && ptype->gso_segment) {
 53.1249 -+			segs = ptype->gso_segment(skb, features);
 53.1250 -+			break;
 53.1251 -+		}
 53.1252 -+	}
 53.1253 -+	rcu_read_unlock();
 53.1254 -+
 53.1255 -+	__skb_push(skb, skb->data - skb->mac.raw);
 53.1256 -+
 53.1257 -+	return segs;
 53.1258 -+}
 53.1259 -+
 53.1260 -+EXPORT_SYMBOL(skb_gso_segment);
 53.1261 -+
 53.1262 - /* Take action when hardware reception checksum errors are detected. */
 53.1263 - #ifdef CONFIG_BUG
 53.1264 - void netdev_rx_csum_fault(struct net_device *dev)
 53.1265 -@@ -1142,75 +1182,108 @@ static inline int illegal_highdma(struct
 53.1266 - #define illegal_highdma(dev, skb)	(0)
 53.1267 - #endif
 53.1268 - 
 53.1269 --/* Keep head the same: replace data */
 53.1270 --int __skb_linearize(struct sk_buff *skb, gfp_t gfp_mask)
 53.1271 -+struct dev_gso_cb {
 53.1272 -+	void (*destructor)(struct sk_buff *skb);
 53.1273 -+};
 53.1274 -+
 53.1275 -+#define DEV_GSO_CB(skb) ((struct dev_gso_cb *)(skb)->cb)
 53.1276 -+
 53.1277 -+static void dev_gso_skb_destructor(struct sk_buff *skb)
 53.1278 -+{
 53.1279 -+	struct dev_gso_cb *cb;
 53.1280 -+
 53.1281 -+	do {
 53.1282 -+		struct sk_buff *nskb = skb->next;
 53.1283 -+
 53.1284 -+		skb->next = nskb->next;
 53.1285 -+		nskb->next = NULL;
 53.1286 -+		kfree_skb(nskb);
 53.1287 -+	} while (skb->next);
 53.1288 -+
 53.1289 -+	cb = DEV_GSO_CB(skb);
 53.1290 -+	if (cb->destructor)
 53.1291 -+		cb->destructor(skb);
 53.1292 -+}
 53.1293 -+
 53.1294 -+/**
 53.1295 -+ *	dev_gso_segment - Perform emulated hardware segmentation on skb.
 53.1296 -+ *	@skb: buffer to segment
 53.1297 -+ *
 53.1298 -+ *	This function segments the given skb and stores the list of segments
 53.1299 -+ *	in skb->next.
 53.1300 -+ */
 53.1301 -+static int dev_gso_segment(struct sk_buff *skb)
 53.1302 - {
 53.1303 --	unsigned int size;
 53.1304 --	u8 *data;
 53.1305 --	long offset;
 53.1306 --	struct skb_shared_info *ninfo;
 53.1307 --	int headerlen = skb->data - skb->head;
 53.1308 --	int expand = (skb->tail + skb->data_len) - skb->end;
 53.1309 --
 53.1310 --	if (skb_shared(skb))
 53.1311 --		BUG();
 53.1312 --
 53.1313 --	if (expand <= 0)
 53.1314 --		expand = 0;
 53.1315 --
 53.1316 --	size = skb->end - skb->head + expand;
 53.1317 --	size = SKB_DATA_ALIGN(size);
 53.1318 --	data = kmalloc(size + sizeof(struct skb_shared_info), gfp_mask);
 53.1319 --	if (!data)
 53.1320 --		return -ENOMEM;
 53.1321 --
 53.1322 --	/* Copy entire thing */
 53.1323 --	if (skb_copy_bits(skb, -headerlen, data, headerlen + skb->len))
 53.1324 --		BUG();
 53.1325 --
 53.1326 --	/* Set up shinfo */
 53.1327 --	ninfo = (struct skb_shared_info*)(data + size);
 53.1328 --	atomic_set(&ninfo->dataref, 1);
 53.1329 --	ninfo->tso_size = skb_shinfo(skb)->tso_size;
 53.1330 --	ninfo->tso_segs = skb_shinfo(skb)->tso_segs;
 53.1331 --	ninfo->nr_frags = 0;
 53.1332 --	ninfo->frag_list = NULL;
 53.1333 --
 53.1334 --	/* Offset between the two in bytes */
 53.1335 --	offset = data - skb->head;
 53.1336 --
 53.1337 --	/* Free old data. */
 53.1338 --	skb_release_data(skb);
 53.1339 --
 53.1340 --	skb->head = data;
 53.1341 --	skb->end  = data + size;
 53.1342 --
 53.1343 --	/* Set up new pointers */
 53.1344 --	skb->h.raw   += offset;
 53.1345 --	skb->nh.raw  += offset;
 53.1346 --	skb->mac.raw += offset;
 53.1347 --	skb->tail    += offset;
 53.1348 --	skb->data    += offset;
 53.1349 -+	struct net_device *dev = skb->dev;
 53.1350 -+	struct sk_buff *segs;
 53.1351 -+	int features = dev->features & ~(illegal_highdma(dev, skb) ?
 53.1352 -+					 NETIF_F_SG : 0);
 53.1353 -+
 53.1354 -+	segs = skb_gso_segment(skb, features);
 53.1355 -+
 53.1356 -+	/* Verifying header integrity only. */
 53.1357 -+	if (!segs)
 53.1358 -+		return 0;
 53.1359 - 
 53.1360 --	/* We are no longer a clone, even if we were. */
 53.1361 --	skb->cloned    = 0;
 53.1362 -+	if (unlikely(IS_ERR(segs)))
 53.1363 -+		return PTR_ERR(segs);
 53.1364 -+
 53.1365 -+	skb->next = segs;
 53.1366 -+	DEV_GSO_CB(skb)->destructor = skb->destructor;
 53.1367 -+	skb->destructor = dev_gso_skb_destructor;
 53.1368 - 
 53.1369 --	skb->tail     += skb->data_len;
 53.1370 --	skb->data_len  = 0;
 53.1371 -+	return 0;
 53.1372 -+}
 53.1373 -+
 53.1374 -+int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 53.1375 -+{
 53.1376 -+	if (likely(!skb->next)) {
 53.1377 -+		if (netdev_nit)
 53.1378 -+			dev_queue_xmit_nit(skb, dev);
 53.1379 -+
 53.1380 -+		if (netif_needs_gso(dev, skb)) {
 53.1381 -+			if (unlikely(dev_gso_segment(skb)))
 53.1382 -+				goto out_kfree_skb;
 53.1383 -+			if (skb->next)
 53.1384 -+				goto gso;
 53.1385 -+		}
 53.1386 -+
 53.1387 -+		return dev->hard_start_xmit(skb, dev);
 53.1388 -+	}
 53.1389 -+
 53.1390 -+gso:
 53.1391 -+	do {
 53.1392 -+		struct sk_buff *nskb = skb->next;
 53.1393 -+		int rc;
 53.1394 -+
 53.1395 -+		skb->next = nskb->next;
 53.1396 -+		nskb->next = NULL;
 53.1397 -+		rc = dev->hard_start_xmit(nskb, dev);
 53.1398 -+		if (unlikely(rc)) {
 53.1399 -+			nskb->next = skb->next;
 53.1400 -+			skb->next = nskb;
 53.1401 -+			return rc;
 53.1402 -+		}
 53.1403 -+		if (unlikely(netif_queue_stopped(dev) && skb->next))
 53.1404 -+			return NETDEV_TX_BUSY;
 53.1405 -+	} while (skb->next);
 53.1406 -+	
 53.1407 -+	skb->destructor = DEV_GSO_CB(skb)->destructor;
 53.1408 -+
 53.1409 -+out_kfree_skb:
 53.1410 -+	kfree_skb(skb);
 53.1411 - 	return 0;
 53.1412 - }
 53.1413 - 
 53.1414 - #define HARD_TX_LOCK(dev, cpu) {			\
 53.1415 - 	if ((dev->features & NETIF_F_LLTX) == 0) {	\
 53.1416 --		spin_lock(&dev->xmit_lock);		\
 53.1417 --		dev->xmit_lock_owner = cpu;		\
 53.1418 -+		netif_tx_lock(dev);			\
 53.1419 - 	}						\
 53.1420 - }
 53.1421 - 
 53.1422 - #define HARD_TX_UNLOCK(dev) {				\
 53.1423 - 	if ((dev->features & NETIF_F_LLTX) == 0) {	\
 53.1424 --		dev->xmit_lock_owner = -1;		\
 53.1425 --		spin_unlock(&dev->xmit_lock);		\
 53.1426 -+		netif_tx_unlock(dev);			\
 53.1427 - 	}						\
 53.1428 - }
 53.1429 - 
 53.1430 -@@ -1246,9 +1319,13 @@ int dev_queue_xmit(struct sk_buff *skb)
 53.1431 - 	struct Qdisc *q;
 53.1432 - 	int rc = -ENOMEM;
 53.1433 - 
 53.1434 -+	/* GSO will handle the following emulations directly. */
 53.1435 -+	if (netif_needs_gso(dev, skb))
 53.1436 -+		goto gso;
 53.1437 -+
 53.1438 - 	if (skb_shinfo(skb)->frag_list &&
 53.1439 - 	    !(dev->features & NETIF_F_FRAGLIST) &&
 53.1440 --	    __skb_linearize(skb, GFP_ATOMIC))
 53.1441 -+	    __skb_linearize(skb))
 53.1442 - 		goto out_kfree_skb;
 53.1443 - 
 53.1444 - 	/* Fragmented skb is linearized if device does not support SG,
 53.1445 -@@ -1257,25 +1334,26 @@ int dev_queue_xmit(struct sk_buff *skb)
 53.1446 - 	 */
 53.1447 - 	if (skb_shinfo(skb)->nr_frags &&
 53.1448 - 	    (!(dev->features & NETIF_F_SG) || illegal_highdma(dev, skb)) &&
 53.1449 --	    __skb_linearize(skb, GFP_ATOMIC))
 53.1450 -+	    __skb_linearize(skb))
 53.1451 - 		goto out_kfree_skb;
 53.1452 - 
 53.1453 - 	/* If packet is not checksummed and device does not support
 53.1454 - 	 * checksumming for this protocol, complete checksumming here.
 53.1455 - 	 */
 53.1456 - 	if (skb->ip_summed == CHECKSUM_HW &&
 53.1457 --	    (!(dev->features & (NETIF_F_HW_CSUM | NETIF_F_NO_CSUM)) &&
 53.1458 -+	    (!(dev->features & NETIF_F_GEN_CSUM) &&
 53.1459 - 	     (!(dev->features & NETIF_F_IP_CSUM) ||
 53.1460 - 	      skb->protocol != htons(ETH_P_IP))))
 53.1461 - 	      	if (skb_checksum_help(skb, 0))
 53.1462 - 	      		goto out_kfree_skb;
 53.1463 - 
 53.1464 -+gso:
 53.1465 - 	spin_lock_prefetch(&dev->queue_lock);
 53.1466 - 
 53.1467 - 	/* Disable soft irqs for various locks below. Also 
 53.1468 - 	 * stops preemption for RCU. 
 53.1469 - 	 */
 53.1470 --	local_bh_disable(); 
 53.1471 -+	rcu_read_lock_bh(); 
 53.1472 - 
 53.1473 - 	/* Updates of qdisc are serialized by queue_lock. 
 53.1474 - 	 * The struct Qdisc which is pointed to by qdisc is now a 
 53.1475 -@@ -1309,8 +1387,8 @@ int dev_queue_xmit(struct sk_buff *skb)
 53.1476 - 	/* The device has no queue. Common case for software devices:
 53.1477 - 	   loopback, all the sorts of tunnels...
 53.1478 - 
 53.1479 --	   Really, it is unlikely that xmit_lock protection is necessary here.
 53.1480 --	   (f.e. loopback and IP tunnels are clean ignoring statistics
 53.1481 -+	   Really, it is unlikely that netif_tx_lock protection is necessary
 53.1482 -+	   here.  (f.e. loopback and IP tunnels are clean ignoring statistics
 53.1483 - 	   counters.)
 53.1484 - 	   However, it is possible, that they rely on protection
 53.1485 - 	   made by us here.
 53.1486 -@@ -1326,11 +1404,8 @@ int dev_queue_xmit(struct sk_buff *skb)
 53.1487 - 			HARD_TX_LOCK(dev, cpu);
 53.1488 - 
 53.1489 - 			if (!netif_queue_stopped(dev)) {
 53.1490 --				if (netdev_nit)
 53.1491 --					dev_queue_xmit_nit(skb, dev);
 53.1492 --
 53.1493 - 				rc = 0;
 53.1494 --				if (!dev->hard_start_xmit(skb, dev)) {
 53.1495 -+				if (!dev_hard_start_xmit(skb, dev)) {
 53.1496 - 					HARD_TX_UNLOCK(dev);
 53.1497 - 					goto out;
 53.1498 - 				}
 53.1499 -@@ -1349,13 +1424,13 @@ int dev_queue_xmit(struct sk_buff *skb)
 53.1500 - 	}
 53.1501 - 
 53.1502 - 	rc = -ENETDOWN;
 53.1503 --	local_bh_enable();
 53.1504 -+	rcu_read_unlock_bh();
 53.1505 - 
 53.1506 - out_kfree_skb:
 53.1507 - 	kfree_skb(skb);
 53.1508 - 	return rc;
 53.1509 - out:
 53.1510 --	local_bh_enable();
 53.1511 -+	rcu_read_unlock_bh();
 53.1512 - 	return rc;
 53.1513 - }
 53.1514 - 
 53.1515 -@@ -2670,7 +2745,7 @@ int register_netdevice(struct net_device
 53.1516 - 	BUG_ON(dev->reg_state != NETREG_UNINITIALIZED);
 53.1517 - 
 53.1518 - 	spin_lock_init(&dev->queue_lock);
 53.1519 --	spin_lock_init(&dev->xmit_lock);
 53.1520 -+	spin_lock_init(&dev->_xmit_lock);
 53.1521 - 	dev->xmit_lock_owner = -1;
 53.1522 - #ifdef CONFIG_NET_CLS_ACT
 53.1523 - 	spin_lock_init(&dev->ingress_lock);
 53.1524 -@@ -2714,9 +2789,7 @@ int register_netdevice(struct net_device
 53.1525 - 
 53.1526 - 	/* Fix illegal SG+CSUM combinations. */
 53.1527 - 	if ((dev->features & NETIF_F_SG) &&
 53.1528 --	    !(dev->features & (NETIF_F_IP_CSUM |
 53.1529 --			       NETIF_F_NO_CSUM |
 53.1530 --			       NETIF_F_HW_CSUM))) {
 53.1531 -+	    !(dev->features & NETIF_F_ALL_CSUM)) {
 53.1532 - 		printk("%s: Dropping NETIF_F_SG since no checksum feature.\n",
 53.1533 - 		       dev->name);
 53.1534 - 		dev->features &= ~NETIF_F_SG;
 53.1535 -@@ -3268,7 +3341,6 @@ subsys_initcall(net_dev_init);
 53.1536 - EXPORT_SYMBOL(__dev_get_by_index);
 53.1537 - EXPORT_SYMBOL(__dev_get_by_name);
 53.1538 - EXPORT_SYMBOL(__dev_remove_pack);
 53.1539 --EXPORT_SYMBOL(__skb_linearize);
 53.1540 - EXPORT_SYMBOL(dev_valid_name);
 53.1541 - EXPORT_SYMBOL(dev_add_pack);
 53.1542 - EXPORT_SYMBOL(dev_alloc_name);
 53.1543 -diff -pruN ../orig-linux-2.6.16.29/net/core/dev_mcast.c ./net/core/dev_mcast.c
 53.1544 ---- ../orig-linux-2.6.16.29/net/core/dev_mcast.c	2006-09-12 19:02:10.000000000 +0100
 53.1545 -+++ ./net/core/dev_mcast.c	2006-09-19 13:59:20.000000000 +0100
 53.1546 -@@ -62,7 +62,7 @@
 53.1547 -  *	Device mc lists are changed by bh at least if IPv6 is enabled,
 53.1548 -  *	so that it must be bh protected.
 53.1549 -  *
 53.1550 -- *	We block accesses to device mc filters with dev->xmit_lock.
 53.1551 -+ *	We block accesses to device mc filters with netif_tx_lock.
 53.1552 -  */
 53.1553 - 
 53.1554 - /*
 53.1555 -@@ -93,9 +93,9 @@ static void __dev_mc_upload(struct net_d
 53.1556 - 
 53.1557 - void dev_mc_upload(struct net_device *dev)
 53.1558 - {
 53.1559 --	spin_lock_bh(&dev->xmit_lock);
 53.1560 -+	netif_tx_lock_bh(dev);
 53.1561 - 	__dev_mc_upload(dev);
 53.1562 --	spin_unlock_bh(&dev->xmit_lock);
 53.1563 -+	netif_tx_unlock_bh(dev);
 53.1564 - }
 53.1565 - 
 53.1566 - /*
 53.1567 -@@ -107,7 +107,7 @@ int dev_mc_delete(struct net_device *dev
 53.1568 - 	int err = 0;
 53.1569 - 	struct dev_mc_list *dmi, **dmip;
 53.1570 - 
 53.1571 --	spin_lock_bh(&dev->xmit_lock);
 53.1572 -+	netif_tx_lock_bh(dev);
 53.1573 - 
 53.1574 - 	for (dmip = &dev->mc_list; (dmi = *dmip) != NULL; dmip = &dmi->next) {
 53.1575 - 		/*
 53.1576 -@@ -139,13 +139,13 @@ int dev_mc_delete(struct net_device *dev
 53.1577 - 			 */
 53.1578 - 			__dev_mc_upload(dev);
 53.1579 - 			
 53.1580 --			spin_unlock_bh(&dev->xmit_lock);
 53.1581 -+			netif_tx_unlock_bh(dev);
 53.1582 - 			return 0;
 53.1583 - 		}
 53.1584 - 	}
 53.1585 - 	err = -ENOENT;
 53.1586 - done:
 53.1587 --	spin_unlock_bh(&dev->xmit_lock);
 53.1588 -+	netif_tx_unlock_bh(dev);
 53.1589 - 	return err;
 53.1590 - }
 53.1591 - 
 53.1592 -@@ -160,7 +160,7 @@ int dev_mc_add(struct net_device *dev, v
 53.1593 - 
 53.1594 - 	dmi1 = kmalloc(sizeof(*dmi), GFP_ATOMIC);
 53.1595 - 
 53.1596 --	spin_lock_bh(&dev->xmit_lock);
 53.1597 -+	netif_tx_lock_bh(dev);
 53.1598 - 	for (dmi = dev->mc_list; dmi != NULL; dmi = dmi->next) {
 53.1599 - 		if (memcmp(dmi->dmi_addr, addr, dmi->dmi_addrlen) == 0 &&
 53.1600 - 		    dmi->dmi_addrlen == alen) {
 53.1601 -@@ -176,7 +176,7 @@ int dev_mc_add(struct net_device *dev, v
 53.1602 - 	}
 53.1603 - 
 53.1604 - 	if ((dmi = dmi1) == NULL) {
 53.1605 --		spin_unlock_bh(&dev->xmit_lock);
 53.1606 -+		netif_tx_unlock_bh(dev);
 53.1607 - 		return -ENOMEM;
 53.1608 - 	}
 53.1609 - 	memcpy(dmi->dmi_addr, addr, alen);
 53.1610 -@@ -189,11 +189,11 @@ int dev_mc_add(struct net_device *dev, v
 53.1611 - 
 53.1612 - 	__dev_mc_upload(dev);
 53.1613 - 	
 53.1614 --	spin_unlock_bh(&dev->xmit_lock);
 53.1615 -+	netif_tx_unlock_bh(dev);
 53.1616 - 	return 0;
 53.1617 - 
 53.1618 - done:
 53.1619 --	spin_unlock_bh(&dev->xmit_lock);
 53.1620 -+	netif_tx_unlock_bh(dev);
 53.1621 - 	kfree(dmi1);
 53.1622 - 	return err;
 53.1623 - }
 53.1624 -@@ -204,7 +204,7 @@ done:
 53.1625 - 
 53.1626 - void dev_mc_discard(struct net_device *dev)
 53.1627 - {
 53.1628 --	spin_lock_bh(&dev->xmit_lock);
 53.1629 -+	netif_tx_lock_bh(dev);
 53.1630 - 	
 53.1631 - 	while (dev->mc_list != NULL) {
 53.1632 - 		struct dev_mc_list *tmp = dev->mc_list;
 53.1633 -@@ -215,7 +215,7 @@ void dev_mc_discard(struct net_device *d
 53.1634 - 	}
 53.1635 - 	dev->mc_count = 0;
 53.1636 - 
 53.1637 --	spin_unlock_bh(&dev->xmit_lock);
 53.1638 -+	netif_tx_unlock_bh(dev);
 53.1639 - }
 53.1640 - 
 53.1641 - #ifdef CONFIG_PROC_FS
 53.1642 -@@ -250,7 +250,7 @@ static int dev_mc_seq_show(struct seq_fi
 53.1643 - 	struct dev_mc_list *m;
 53.1644 - 	struct net_device *dev = v;
 53.1645 - 
 53.1646 --	spin_lock_bh(&dev->xmit_lock);
 53.1647 -+	netif_tx_lock_bh(dev);
 53.1648 - 	for (m = dev->mc_list; m; m = m->next) {
 53.1649 - 		int i;
 53.1650 - 
 53.1651 -@@ -262,7 +262,7 @@ static int dev_mc_seq_show(struct seq_fi
 53.1652 - 
 53.1653 - 		seq_putc(seq, '\n');
 53.1654 - 	}
 53.1655 --	spin_unlock_bh(&dev->xmit_lock);
 53.1656 -+	netif_tx_unlock_bh(dev);
 53.1657 - 	return 0;
 53.1658 - }
 53.1659 - 
 53.1660 -diff -pruN ../orig-linux-2.6.16.29/net/core/ethtool.c ./net/core/ethtool.c
 53.1661 ---- ../orig-linux-2.6.16.29/net/core/ethtool.c	2006-09-12 19:02:10.000000000 +0100
 53.1662 -+++ ./net/core/ethtool.c	2006-09-19 13:59:20.000000000 +0100
 53.1663 -@@ -30,7 +30,7 @@ u32 ethtool_op_get_link(struct net_devic
 53.1664 - 
 53.1665 - u32 ethtool_op_get_tx_csum(struct net_device *dev)
 53.1666 - {
 53.1667 --	return (dev->features & (NETIF_F_IP_CSUM | NETIF_F_HW_CSUM)) != 0;
 53.1668 -+	return (dev->features & NETIF_F_ALL_CSUM) != 0;
 53.1669 - }
 53.1670 - 
 53.1671 - int ethtool_op_set_tx_csum(struct net_device *dev, u32 data)
 53.1672 -@@ -551,9 +551,7 @@ static int ethtool_set_sg(struct net_dev
 53.1673 - 		return -EFAULT;
 53.1674 - 
 53.1675 - 	if (edata.data && 
 53.1676 --	    !(dev->features & (NETIF_F_IP_CSUM |
 53.1677 --			       NETIF_F_NO_CSUM |
 53.1678 --			       NETIF_F_HW_CSUM)))
 53.1679 -+	    !(dev->features & NETIF_F_ALL_CSUM))
 53.1680 - 		return -EINVAL;
 53.1681 - 
 53.1682 - 	return __ethtool_set_sg(dev, edata.data);
 53.1683 -@@ -561,7 +559,7 @@ static int ethtool_set_sg(struct net_dev
 53.1684 - 
 53.1685 - static int ethtool_get_tso(struct net_device *dev, char __user *useraddr)
 53.1686 - {
 53.1687 --	struct ethtool_value edata = { ETHTOOL_GTSO };
 53.1688 -+	struct ethtool_value edata = { ETHTOOL_GUFO };
 53.1689 - 
 53.1690 - 	if (!dev->ethtool_ops->get_tso)
 53.1691 - 		return -EOPNOTSUPP;
 53.1692 -@@ -616,6 +614,29 @@ static int ethtool_set_ufo(struct net_de
 53.1693 - 	return dev->ethtool_ops->set_ufo(dev, edata.data);
 53.1694 - }
 53.1695 - 
 53.1696 -+static int ethtool_get_gso(struct net_device *dev, char __user *useraddr)
 53.1697 -+{
 53.1698 -+	struct ethtool_value edata = { ETHTOOL_GGSO };
 53.1699 -+
 53.1700 -+	edata.data = dev->features & NETIF_F_GSO;
 53.1701 -+	if (copy_to_user(useraddr, &edata, sizeof(edata)))
 53.1702 -+		 return -EFAULT;
 53.1703 -+	return 0;
 53.1704 -+}
 53.1705 -+
 53.1706 -+static int ethtool_set_gso(struct net_device *dev, char __user *useraddr)
 53.1707 -+{
 53.1708 -+	struct ethtool_value edata;
 53.1709 -+
 53.1710 -+	if (copy_from_user(&edata, useraddr, sizeof(edata)))
 53.1711 -+		return -EFAULT;
 53.1712 -+	if (edata.data)
 53.1713 -+		dev->features |= NETIF_F_GSO;
 53.1714 -+	else
 53.1715 -+		dev->features &= ~NETIF_F_GSO;
 53.1716 -+	return 0;
 53.1717 -+}
 53.1718 -+
 53.1719 - static int ethtool_self_test(struct net_device *dev, char __user *useraddr)
 53.1720 - {
 53.1721 - 	struct ethtool_test test;
 53.1722 -@@ -907,6 +928,12 @@ int dev_ethtool(struct ifreq *ifr)
 53.1723 - 	case ETHTOOL_SUFO:
 53.1724 - 		rc = ethtool_set_ufo(dev, useraddr);
 53.1725 - 		break;
 53.1726 -+	case ETHTOOL_GGSO:
 53.1727 -+		rc = ethtool_get_gso(dev, useraddr);
 53.1728 -+		break;
 53.1729 -+	case ETHTOOL_SGSO:
 53.1730 -+		rc = ethtool_set_gso(dev, useraddr);
 53.1731 -+		break;
 53.1732 - 	default:
 53.1733 - 		rc =  -EOPNOTSUPP;
 53.1734 - 	}
 53.1735 -diff -pruN ../orig-linux-2.6.16.29/net/core/netpoll.c ./net/core/netpoll.c
 53.1736 ---- ../orig-linux-2.6.16.29/net/core/netpoll.c	2006-09-12 19:02:10.000000000 +0100
 53.1737 -+++ ./net/core/netpoll.c	2006-09-19 13:59:20.000000000 +0100
 53.1738 -@@ -273,24 +273,21 @@ static void netpoll_send_skb(struct netp
 53.1739 - 
 53.1740 - 	do {
 53.1741 - 		npinfo->tries--;
 53.1742 --		spin_lock(&np->dev->xmit_lock);
 53.1743 --		np->dev->xmit_lock_owner = smp_processor_id();
 53.1744 -+		netif_tx_lock(np->dev);
 53.1745 - 
 53.1746 - 		/*
 53.1747 - 		 * network drivers do not expect to be called if the queue is
 53.1748 - 		 * stopped.
 53.1749 - 		 */
 53.1750 - 		if (netif_queue_stopped(np->dev)) {
 53.1751 --			np->dev->xmit_lock_owner = -1;
 53.1752 --			spin_unlock(&np->dev->xmit_lock);
 53.1753 -+			netif_tx_unlock(np->dev);
 53.1754 - 			netpoll_poll(np);
 53.1755 - 			udelay(50);
 53.1756 - 			continue;
 53.1757 - 		}
 53.1758 - 
 53.1759 - 		status = np->dev->hard_start_xmit(skb, np->dev);
 53.1760 --		np->dev->xmit_lock_owner = -1;
 53.1761 --		spin_unlock(&np->dev->xmit_lock);
 53.1762 -+		netif_tx_unlock(np->dev);
 53.1763 - 
 53.1764 - 		/* success */
 53.1765 - 		if(!status) {
 53.1766 -diff -pruN ../orig-linux-2.6.16.29/net/core/pktgen.c ./net/core/pktgen.c
 53.1767 ---- ../orig-linux-2.6.16.29/net/core/pktgen.c	2006-09-12 19:02:10.000000000 +0100
 53.1768 -+++ ./net/core/pktgen.c	2006-09-19 13:59:20.000000000 +0100
 53.1769 -@@ -2586,7 +2586,7 @@ static __inline__ void pktgen_xmit(struc
 53.1770 - 		}
 53.1771 - 	}
 53.1772 - 	
 53.1773 --	spin_lock_bh(&odev->xmit_lock);
 53.1774 -+	netif_tx_lock_bh(odev);
 53.1775 - 	if (!netif_queue_stopped(odev)) {
 53.1776 - 
 53.1777 - 		atomic_inc(&(pkt_dev->skb->users));
 53.1778 -@@ -2631,7 +2631,7 @@ retry_now:
 53.1779 - 		pkt_dev->next_tx_ns = 0;
 53.1780 -         }
 53.1781 - 
 53.1782 --	spin_unlock_bh(&odev->xmit_lock);
 53.1783 -+	netif_tx_unlock_bh(odev);
 53.1784 - 	
 53.1785 - 	/* If pkt_dev->count is zero, then run forever */
 53.1786 - 	if ((pkt_dev->count != 0) && (pkt_dev->sofar >= pkt_dev->count)) {
 53.1787 -diff -pruN ../orig-linux-2.6.16.29/net/core/skbuff.c ./net/core/skbuff.c
 53.1788 ---- ../orig-linux-2.6.16.29/net/core/skbuff.c	2006-09-12 19:02:10.000000000 +0100
 53.1789 -+++ ./net/core/skbuff.c	2006-09-19 13:59:20.000000000 +0100
 53.1790 -@@ -164,9 +164,9 @@ struct sk_buff *__alloc_skb(unsigned int
 53.1791 - 	shinfo = skb_shinfo(skb);
 53.1792 - 	atomic_set(&shinfo->dataref, 1);
 53.1793 - 	shinfo->nr_frags  = 0;
 53.1794 --	shinfo->tso_size = 0;
 53.1795 --	shinfo->tso_segs = 0;
 53.1796 --	shinfo->ufo_size = 0;
 53.1797 -+	shinfo->gso_size = 0;
 53.1798 -+	shinfo->gso_segs = 0;
 53.1799 -+	shinfo->gso_type = 0;
 53.1800 - 	shinfo->ip6_frag_id = 0;
 53.1801 - 	shinfo->frag_list = NULL;
 53.1802 - 
 53.1803 -@@ -230,8 +230,9 @@ struct sk_buff *alloc_skb_from_cache(kme
 53.1804 - 
 53.1805 - 	atomic_set(&(skb_shinfo(skb)->dataref), 1);
 53.1806 - 	skb_shinfo(skb)->nr_frags  = 0;
 53.1807 --	skb_shinfo(skb)->tso_size = 0;
 53.1808 --	skb_shinfo(skb)->tso_segs = 0;
 53.1809 -+	skb_shinfo(skb)->gso_size = 0;
 53.1810 -+	skb_shinfo(skb)->gso_segs = 0;
 53.1811 -+	skb_shinfo(skb)->gso_type = 0;
 53.1812 - 	skb_shinfo(skb)->frag_list = NULL;
 53.1813 - out:
 53.1814 - 	return skb;
 53.1815 -@@ -501,8 +502,9 @@ static void copy_skb_header(struct sk_bu
 53.1816 - 	new->tc_index	= old->tc_index;
 53.1817 - #endif
 53.1818 - 	atomic_set(&new->users, 1);
 53.1819 --	skb_shinfo(new)->tso_size = skb_shinfo(old)->tso_size;
 53.1820 --	skb_shinfo(new)->tso_segs = skb_shinfo(old)->tso_segs;
 53.1821 -+	skb_shinfo(new)->gso_size = skb_shinfo(old)->gso_size;
 53.1822 -+	skb_shinfo(new)->gso_segs = skb_shinfo(old)->gso_segs;
 53.1823 -+	skb_shinfo(new)->gso_type = skb_shinfo(old)->gso_type;
 53.1824 - }
 53.1825 - 
 53.1826 - /**
 53.1827 -@@ -1777,6 +1779,133 @@ int skb_append_datato_frags(struct sock 
 53.1828 - 	return 0;
 53.1829 - }
 53.1830 - 
 53.1831 -+/**
 53.1832 -+ *	skb_segment - Perform protocol segmentation on skb.
 53.1833 -+ *	@skb: buffer to segment
 53.1834 -+ *	@features: features for the output path (see dev->features)
 53.1835 -+ *
 53.1836 -+ *	This function performs segmentation on the given skb.  It returns
 53.1837 -+ *	the segment at the given position.  It returns NULL if there are
 53.1838 -+ *	no more segments to generate, or when an error is encountered.
 53.1839 -+ */
 53.1840 -+struct sk_buff *skb_segment(struct sk_buff *skb, int features)
 53.1841 -+{
 53.1842 -+	struct sk_buff *segs = NULL;
 53.1843 -+	struct sk_buff *tail = NULL;
 53.1844 -+	unsigned int mss = skb_shinfo(skb)->gso_size;
 53.1845 -+	unsigned int doffset = skb->data - skb->mac.raw;
 53.1846 -+	unsigned int offset = doffset;
 53.1847 -+	unsigned int headroom;
 53.1848 -+	unsigned int len;
 53.1849 -+	int sg = features & NETIF_F_SG;
 53.1850 -+	int nfrags = skb_shinfo(skb)->nr_frags;
 53.1851 -+	int err = -ENOMEM;
 53.1852 -+	int i = 0;
 53.1853 -+	int pos;
 53.1854 -+
 53.1855 -+	__skb_push(skb, doffset);
 53.1856 -+	headroom = skb_headroom(skb);
 53.1857 -+	pos = skb_headlen(skb);
 53.1858 -+
 53.1859 -+	do {
 53.1860 -+		struct sk_buff *nskb;
 53.1861 -+		skb_frag_t *frag;
 53.1862 -+		int hsize, nsize;
 53.1863 -+		int k;
 53.1864 -+		int size;
 53.1865 -+
 53.1866 -+		len = skb->len - offset;
 53.1867 -+		if (len > mss)
 53.1868 -+			len = mss;
 53.1869 -+
 53.1870 -+		hsize = skb_headlen(skb) - offset;
 53.1871 -+		if (hsize < 0)
 53.1872 -+			hsize = 0;
 53.1873 -+		nsize = hsize + doffset;
 53.1874 -+		if (nsize > len + doffset || !sg)
 53.1875 -+			nsize = len + doffset;
 53.1876 -+
 53.1877 -+		nskb = alloc_skb(nsize + headroom, GFP_ATOMIC);
 53.1878 -+		if (unlikely(!nskb))
 53.1879 -+			goto err;
 53.1880 -+
 53.1881 -+		if (segs)
 53.1882 -+			tail->next = nskb;
 53.1883 -+		else
 53.1884 -+			segs = nskb;
 53.1885 -+		tail = nskb;
 53.1886 -+
 53.1887 -+		nskb->dev = skb->dev;
 53.1888 -+		nskb->priority = skb->priority;
 53.1889 -+		nskb->protocol = skb->protocol;
 53.1890 -+		nskb->dst = dst_clone(skb->dst);
 53.1891 -+		memcpy(nskb->cb, skb->cb, sizeof(skb->cb));
 53.1892 -+		nskb->pkt_type = skb->pkt_type;
 53.1893 -+		nskb->mac_len = skb->mac_len;
 53.1894 -+
 53.1895 -+		skb_reserve(nskb, headroom);
 53.1896 -+		nskb->mac.raw = nskb->data;
 53.1897 -+		nskb->nh.raw = nskb->data + skb->mac_len;
 53.1898 -+		nskb->h.raw = nskb->nh.raw + (skb->h.raw - skb->nh.raw);
 53.1899 -+		memcpy(skb_put(nskb, doffset), skb->data, doffset);
 53.1900 -+
 53.1901 -+		if (!sg) {
 53.1902 -+			nskb->csum = skb_copy_and_csum_bits(skb, offset,
 53.1903 -+							    skb_put(nskb, len),
 53.1904 -+							    len, 0);
 53.1905 -+			continue;
 53.1906 -+		}
 53.1907 -+
 53.1908 -+		frag = skb_shinfo(nskb)->frags;
 53.1909 -+		k = 0;
 53.1910 -+
 53.1911 -+		nskb->ip_summed = CHECKSUM_HW;
 53.1912 -+		nskb->csum = skb->csum;
 53.1913 -+		memcpy(skb_put(nskb, hsize), skb->data + offset, hsize);
 53.1914 -+
 53.1915 -+		while (pos < offset + len) {
 53.1916 -+			BUG_ON(i >= nfrags);
 53.1917 -+
 53.1918 -+			*frag = skb_shinfo(skb)->frags[i];
 53.1919 -+			get_page(frag->page);
 53.1920 -+			size = frag->size;
 53.1921 -+
 53.1922 -+			if (pos < offset) {
 53.1923 -+				frag->page_offset += offset - pos;
 53.1924 -+				frag->size -= offset - pos;
 53.1925 -+			}
 53.1926 -+
 53.1927 -+			k++;
 53.1928 -+
 53.1929 -+			if (pos + size <= offset + len) {
 53.1930 -+				i++;
 53.1931 -+				pos += size;
 53.1932 -+			} else {
 53.1933 -+				frag->size -= pos + size - (offset + len);
 53.1934 -+				break;
 53.1935 -+			}
 53.1936 -+
 53.1937 -+			frag++;
 53.1938 -+		}
 53.1939 -+
 53.1940 -+		skb_shinfo(nskb)->nr_frags = k;
 53.1941 -+		nskb->data_len = len - hsize;
 53.1942 -+		nskb->len += nskb->data_len;
 53.1943 -+		nskb->truesize += nskb->data_len;
 53.1944 -+	} while ((offset += len) < skb->len);
 53.1945 -+
 53.1946 -+	return segs;
 53.1947 -+
 53.1948 -+err:
 53.1949 -+	while ((skb = segs)) {
 53.1950 -+		segs = skb->next;
 53.1951 -+		kfree(skb);
 53.1952 -+	}
 53.1953 -+	return ERR_PTR(err);
 53.1954 -+}
 53.1955 -+
 53.1956 -+EXPORT_SYMBOL_GPL(skb_segment);
 53.1957 -+
 53.1958 - void __init skb_init(void)
 53.1959 - {
 53.1960 - 	skbuff_head_cache = kmem_cache_create("skbuff_head_cache",
 53.1961 -diff -pruN ../orig-linux-2.6.16.29/net/decnet/dn_nsp_in.c ./net/decnet/dn_nsp_in.c
 53.1962 ---- ../orig-linux-2.6.16.29/net/decnet/dn_nsp_in.c	2006-09-12 19:02:10.000000000 +0100
 53.1963 -+++ ./net/decnet/dn_nsp_in.c	2006-09-19 13:59:20.000000000 +0100
 53.1964 -@@ -801,8 +801,7 @@ got_it:
 53.1965 - 		 * We linearize everything except data segments here.
 53.1966 - 		 */
 53.1967 - 		if (cb->nsp_flags & ~0x60) {
 53.1968 --			if (unlikely(skb_is_nonlinear(skb)) &&
 53.1969 --			    skb_linearize(skb, GFP_ATOMIC) != 0)
 53.1970 -+			if (unlikely(skb_linearize(skb)))
 53.1971 - 				goto free_out;
 53.1972 - 		}
 53.1973 - 
 53.1974 -diff -pruN ../orig-linux-2.6.16.29/net/decnet/dn_route.c ./net/decnet/dn_route.c
 53.1975 ---- ../orig-linux-2.6.16.29/net/decnet/dn_route.c	2006-09-12 19:02:10.000000000 +0100
 53.1976 -+++ ./net/decnet/dn_route.c	2006-09-19 13:59:20.000000000 +0100
 53.1977 -@@ -629,8 +629,7 @@ int dn_route_rcv(struct sk_buff *skb, st
 53.1978 - 			padlen);
 53.1979 - 
 53.1980 -         if (flags & DN_RT_PKT_CNTL) {
 53.1981 --		if (unlikely(skb_is_nonlinear(skb)) &&
 53.1982 --		    skb_linearize(skb, GFP_ATOMIC) != 0)
 53.1983 -+		if (unlikely(skb_linearize(skb)))
 53.1984 - 			goto dump_it;
 53.1985 - 
 53.1986 -                 switch(flags & DN_RT_CNTL_MSK) {
 53.1987 -diff -pruN ../orig-linux-2.6.16.29/net/ipv4/af_inet.c ./net/ipv4/af_inet.c
 53.1988 ---- ../orig-linux-2.6.16.29/net/ipv4/af_inet.c	2006-09-12 19:02:10.000000000 +0100
 53.1989 -+++ ./net/ipv4/af_inet.c	2006-09-19 13:59:20.000000000 +0100
 53.1990 -@@ -68,6 +68,7 @@
 53.1991 -  */
 53.1992 - 
 53.1993 - #include <linux/config.h>
 53.1994 -+#include <linux/err.h>
 53.1995 - #include <linux/errno.h>
 53.1996 - #include <linux/types.h>
 53.1997 - #include <linux/socket.h>
 53.1998 -@@ -1084,6 +1085,54 @@ int inet_sk_rebuild_header(struct sock *
 53.1999 - 
 53.2000 - EXPORT_SYMBOL(inet_sk_rebuild_header);
 53.2001 - 
 53.2002 -+static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int features)
 53.2003 -+{
 53.2004 -+	struct sk_buff *segs = ERR_PTR(-EINVAL);
 53.2005 -+	struct iphdr *iph;
 53.2006 -+	struct net_protocol *ops;
 53.2007 -+	int proto;
 53.2008 -+	int ihl;
 53.2009 -+	int id;
 53.2010 -+
 53.2011 -+	if (!pskb_may_pull(skb, sizeof(*iph)))
 53.2012 -+		goto out;
 53.2013 -+
 53.2014 -+	iph = skb->nh.iph;
 53.2015 -+	ihl = iph->ihl * 4;
 53.2016 -+	if (ihl < sizeof(*iph))
 53.2017 -+		goto out;
 53.2018 -+
 53.2019 -+	if (!pskb_may_pull(skb, ihl))
 53.2020 -+		goto out;
 53.2021 -+
 53.2022 -+	skb->h.raw = __skb_pull(skb, ihl);
 53.2023 -+	iph = skb->nh.iph;
 53.2024 -+	id = ntohs(iph->id);
 53.2025 -+	proto = iph->protocol & (MAX_INET_PROTOS - 1);
 53.2026 -+	segs = ERR_PTR(-EPROTONOSUPPORT);
 53.2027 -+
 53.2028 -+	rcu_read_lock();
 53.2029 -+	ops = rcu_dereference(inet_protos[proto]);
 53.2030 -+	if (ops && ops->gso_segment)
 53.2031 -+		segs = ops->gso_segment(skb, features);
 53.2032 -+	rcu_read_unlock();
 53.2033 -+
 53.2034 -+	if (!segs || unlikely(IS_ERR(segs)))
 53.2035 -+		goto out;
 53.2036 -+
 53.2037 -+	skb = segs;
 53.2038 -+	do {
 53.2039 -+		iph = skb->nh.iph;
 53.2040 -+		iph->id = htons(id++);
 53.2041 -+		iph->tot_len = htons(skb->len - skb->mac_len);
 53.2042 -+		iph->check = 0;
 53.2043 -+		iph->check = ip_fast_csum(skb->nh.raw, iph->ihl);
 53.2044 -+	} while ((skb = skb->next));
 53.2045 -+
 53.2046 -+out:
 53.2047 -+	return segs;
 53.2048 -+}
 53.2049 -+
 53.2050 - #ifdef CONFIG_IP_MULTICAST
 53.2051 - static struct net_protocol igmp_protocol = {
 53.2052 - 	.handler =	igmp_rcv,
 53.2053 -@@ -1093,6 +1142,7 @@ static struct net_protocol igmp_protocol
 53.2054 - static struct net_protocol tcp_protocol = {
 53.2055 - 	.handler =	tcp_v4_rcv,
 53.2056 - 	.err_handler =	tcp_v4_err,
 53.2057 -+	.gso_segment =	tcp_tso_segment,
 53.2058 - 	.no_policy =	1,
 53.2059 - };
 53.2060 - 
 53.2061 -@@ -1138,6 +1188,7 @@ static int ipv4_proc_init(void);
 53.2062 - static struct packet_type ip_packet_type = {
 53.2063 - 	.type = __constant_htons(ETH_P_IP),
 53.2064 - 	.func = ip_rcv,
 53.2065 -+	.gso_segment = inet_gso_segment,
 53.2066 - };
 53.2067 - 
 53.2068 - static int __init inet_init(void)
 53.2069 -diff -pruN ../orig-linux-2.6.16.29/net/ipv4/ip_output.c ./net/ipv4/ip_output.c
 53.2070 ---- ../orig-linux-2.6.16.29/net/ipv4/ip_output.c	2006-09-12 19:02:10.000000000 +0100
 53.2071 -+++ ./net/ipv4/ip_output.c	2006-09-19 13:59:20.000000000 +0100
 53.2072 -@@ -210,8 +210,7 @@ static inline int ip_finish_output(struc
 53.2073 - 		return dst_output(skb);
 53.2074 - 	}
 53.2075 - #endif
 53.2076 --	if (skb->len > dst_mtu(skb->dst) &&
 53.2077 --	    !(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size))
 53.2078 -+	if (skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->gso_size)
 53.2079 - 		return ip_fragment(skb, ip_finish_output2);
 53.2080 - 	else
 53.2081 - 		return ip_finish_output2(skb);
 53.2082 -@@ -362,7 +361,7 @@ packet_routed:
 53.2083 - 	}
 53.2084 - 
 53.2085 - 	ip_select_ident_more(iph, &rt->u.dst, sk,
 53.2086 --			     (skb_shinfo(skb)->tso_segs ?: 1) - 1);
 53.2087 -+			     (skb_shinfo(skb)->gso_segs ?: 1) - 1);
 53.2088 - 
 53.2089 - 	/* Add an IP checksum. */
 53.2090 - 	ip_send_check(iph);
 53.2091 -@@ -743,7 +742,8 @@ static inline int ip_ufo_append_data(str
 53.2092 - 			       (length - transhdrlen));
 53.2093 - 	if (!err) {
 53.2094 - 		/* specify the length of each IP datagram fragment*/
 53.2095 --		skb_shinfo(skb)->ufo_size = (mtu - fragheaderlen);
 53.2096 -+		skb_shinfo(skb)->gso_size = mtu - fragheaderlen;
 53.2097 -+		skb_shinfo(skb)->gso_type = SKB_GSO_UDPV4;
 53.2098 - 		__skb_queue_tail(&sk->sk_write_queue, skb);
 53.2099 - 
 53.2100 - 		return 0;
 53.2101 -@@ -839,7 +839,7 @@ int ip_append_data(struct sock *sk,
 53.2102 - 	 */
 53.2103 - 	if (transhdrlen &&
 53.2104 - 	    length + fragheaderlen <= mtu &&
 53.2105 --	    rt->u.dst.dev->features&(NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM) &&
 53.2106 -+	    rt->u.dst.dev->features & NETIF_F_ALL_CSUM &&
 53.2107 - 	    !exthdrlen)
 53.2108 - 		csummode = CHECKSUM_HW;
 53.2109 - 
 53.2110 -@@ -1086,14 +1086,16 @@ ssize_t	ip_append_page(struct sock *sk, 
 53.2111 - 
 53.2112 - 	inet->cork.length += size;
 53.2113 - 	if ((sk->sk_protocol == IPPROTO_UDP) &&
 53.2114 --	    (rt->u.dst.dev->features & NETIF_F_UFO))
 53.2115 --		skb_shinfo(skb)->ufo_size = (mtu - fragheaderlen);
 53.2116 -+	    (rt->u.dst.dev->features & NETIF_F_UFO)) {
 53.2117 -+		skb_shinfo(skb)->gso_size = mtu - fragheaderlen;
 53.2118 -+		skb_shinfo(skb)->gso_type = SKB_GSO_UDPV4;
 53.2119 -+	}
 53.2120 - 
 53.2121 - 
 53.2122 - 	while (size > 0) {
 53.2123 - 		int i;
 53.2124 - 
 53.2125 --		if (skb_shinfo(skb)->ufo_size)
 53.2126 -+		if (skb_shinfo(skb)->gso_size)
 53.2127 - 			len = size;
 53.2128 - 		else {
 53.2129 - 
 53.2130 -diff -pruN ../orig-linux-2.6.16.29/net/ipv4/ipcomp.c ./net/ipv4/ipcomp.c
 53.2131 ---- ../orig-linux-2.6.16.29/net/ipv4/ipcomp.c	2006-09-12 19:02:10.000000000 +0100
 53.2132 -+++ ./net/ipv4/ipcomp.c	2006-09-19 13:59:20.000000000 +0100
 53.2133 -@@ -84,7 +84,7 @@ static int ipcomp_input(struct xfrm_stat
 53.2134 -                         struct xfrm_decap_state *decap, struct sk_buff *skb)
 53.2135 - {
 53.2136 - 	u8 nexthdr;
 53.2137 --	int err = 0;
 53.2138 -+	int err = -ENOMEM;
 53.2139 - 	struct iphdr *iph;
 53.2140 - 	union {
 53.2141 - 		struct iphdr	iph;
 53.2142 -@@ -92,11 +92,8 @@ static int ipcomp_input(struct xfrm_stat
 53.2143 - 	} tmp_iph;
 53.2144 - 
 53.2145 - 
 53.2146 --	if ((skb_is_nonlinear(skb) || skb_cloned(skb)) &&
 53.2147 --	    skb_linearize(skb, GFP_ATOMIC) != 0) {
 53.2148 --	    	err = -ENOMEM;
 53.2149 -+	if (skb_linearize_cow(skb))
 53.2150 - 	    	goto out;
 53.2151 --	}
 53.2152 - 
 53.2153 - 	skb->ip_summed = CHECKSUM_NONE;
 53.2154 - 
 53.2155 -@@ -171,10 +168,8 @@ static int ipcomp_output(struct xfrm_sta
 53.2156 - 		goto out_ok;
 53.2157 - 	}
 53.2158 - 
 53.2159 --	if ((skb_is_nonlinear(skb) || skb_cloned(skb)) &&
 53.2160 --	    skb_linearize(skb, GFP_ATOMIC) != 0) {
 53.2161 -+	if (skb_linearize_cow(skb))
 53.2162 - 		goto out_ok;
 53.2163 --	}
 53.2164 - 	
 53.2165 - 	err = ipcomp_compress(x, skb);
 53.2166 - 	iph = skb->nh.iph;
 53.2167 -diff -pruN ../orig-linux-2.6.16.29/net/ipv4/tcp.c ./net/ipv4/tcp.c
 53.2168 ---- ../orig-linux-2.6.16.29/net/ipv4/tcp.c	2006-09-12 19:02:10.000000000 +0100
 53.2169 -+++ ./net/ipv4/tcp.c	2006-09-19 13:59:20.000000000 +0100
 53.2170 -@@ -257,6 +257,7 @@
 53.2171 - #include <linux/fs.h>
 53.2172 - #include <linux/random.h>
 53.2173 - #include <linux/bootmem.h>
 53.2174 -+#include <linux/err.h>
 53.2175 - 
 53.2176 - #include <net/icmp.h>
 53.2177 - #include <net/tcp.h>
 53.2178 -@@ -570,7 +571,7 @@ new_segment:
 53.2179 - 		skb->ip_summed = CHECKSUM_HW;
 53.2180 - 		tp->write_seq += copy;
 53.2181 - 		TCP_SKB_CB(skb)->end_seq += copy;
 53.2182 --		skb_shinfo(skb)->tso_segs = 0;
 53.2183 -+		skb_shinfo(skb)->gso_segs = 0;
 53.2184 - 
 53.2185 - 		if (!copied)
 53.2186 - 			TCP_SKB_CB(skb)->flags &= ~TCPCB_FLAG_PSH;
 53.2187 -@@ -621,14 +622,10 @@ ssize_t tcp_sendpage(struct socket *sock
 53.2188 - 	ssize_t res;
 53.2189 - 	struct sock *sk = sock->sk;
 53.2190 - 
 53.2191 --#define TCP_ZC_CSUM_FLAGS (NETIF_F_IP_CSUM | NETIF_F_NO_CSUM | NETIF_F_HW_CSUM)
 53.2192 --
 53.2193 - 	if (!(sk->sk_route_caps & NETIF_F_SG) ||
 53.2194 --	    !(sk->sk_route_caps & TCP_ZC_CSUM_FLAGS))
 53.2195 -+	    !(sk->sk_route_caps & NETIF_F_ALL_CSUM))
 53.2196 - 		return sock_no_sendpage(sock, page, offset, size, flags);
 53.2197 - 
 53.2198 --#undef TCP_ZC_CSUM_FLAGS
 53.2199 --
 53.2200 - 	lock_sock(sk);
 53.2201 - 	TCP_CHECK_TIMER(sk);
 53.2202 - 	res = do_tcp_sendpages(sk, &page, offset, size, flags);
 53.2203 -@@ -725,9 +722,7 @@ new_segment:
 53.2204 - 				/*
 53.2205 - 				 * Check whether we can use HW checksum.
 53.2206 - 				 */
 53.2207 --				if (sk->sk_route_caps &
 53.2208 --				    (NETIF_F_IP_CSUM | NETIF_F_NO_CSUM |
 53.2209 --				     NETIF_F_HW_CSUM))
 53.2210 -+				if (sk->sk_route_caps & NETIF_F_ALL_CSUM)
 53.2211 - 					skb->ip_summed = CHECKSUM_HW;
 53.2212 - 
 53.2213 - 				skb_entail(sk, tp, skb);
 53.2214 -@@ -823,7 +818,7 @@ new_segment:
 53.2215 - 
 53.2216 - 			tp->write_seq += copy;
 53.2217 - 			TCP_SKB_CB(skb)->end_seq += copy;
 53.2218 --			skb_shinfo(skb)->tso_segs = 0;
 53.2219 -+			skb_shinfo(skb)->gso_segs = 0;
 53.2220 - 
 53.2221 - 			from += copy;
 53.2222 - 			copied += copy;
 53.2223 -@@ -2026,6 +2021,71 @@ int tcp_getsockopt(struct sock *sk, int 
 53.2224 - }
 53.2225 - 
 53.2226 - 
 53.2227 -+struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features)
 53.2228 -+{
 53.2229 -+	struct sk_buff *segs = ERR_PTR(-EINVAL);
 53.2230 -+	struct tcphdr *th;
 53.2231 -+	unsigned thlen;
 53.2232 -+	unsigned int seq;
 53.2233 -+	unsigned int delta;
 53.2234 -+	unsigned int oldlen;
 53.2235 -+	unsigned int len;
 53.2236 -+
 53.2237 -+	if (!pskb_may_pull(skb, sizeof(*th)))
 53.2238 -+		goto out;
 53.2239 -+
 53.2240 -+	th = skb->h.th;
 53.2241 -+	thlen = th->doff * 4;
 53.2242 -+	if (thlen < sizeof(*th))
 53.2243 -+		goto out;
 53.2244 -+
 53.2245 -+	if (!pskb_may_pull(skb, thlen))
 53.2246 -+		goto out;
 53.2247 -+
 53.2248 -+	segs = NULL;
 53.2249 -+	if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST))
 53.2250 -+		goto out;
 53.2251 -+
 53.2252 -+	oldlen = (u16)~skb->len;
 53.2253 -+	__skb_pull(skb, thlen);
 53.2254 -+
 53.2255 -+	segs = skb_segment(skb, features);
 53.2256 -+	if (IS_ERR(segs))
 53.2257 -+		goto out;
 53.2258 -+
 53.2259 -+	len = skb_shinfo(skb)->gso_size;
 53.2260 -+	delta = htonl(oldlen + (thlen + len));
 53.2261 -+
 53.2262 -+	skb = segs;
 53.2263 -+	th = skb->h.th;
 53.2264 -+	seq = ntohl(th->seq);
 53.2265 -+
 53.2266 -+	do {
 53.2267 -+		th->fin = th->psh = 0;
 53.2268 -+
 53.2269 -+		th->check = ~csum_fold(th->check + delta);
 53.2270 -+		if (skb->ip_summed != CHECKSUM_HW)
 53.2271 -+			th->check = csum_fold(csum_partial(skb->h.raw, thlen,
 53.2272 -+							   skb->csum));
 53.2273 -+
 53.2274 -+		seq += len;
 53.2275 -+		skb = skb->next;
 53.2276 -+		th = skb->h.th;
 53.2277 -+
 53.2278 -+		th->seq = htonl(seq);
 53.2279 -+		th->cwr = 0;
 53.2280 -+	} while (skb->next);
 53.2281 -+
 53.2282 -+	delta = htonl(oldlen + (skb->tail - skb->h.raw) + skb->data_len);
 53.2283 -+	th->check = ~csum_fold(th->check + delta);
 53.2284 -+	if (skb->ip_summed != CHECKSUM_HW)
 53.2285 -+		th->check = csum_fold(csum_partial(skb->h.raw, thlen,
 53.2286 -+						   skb->csum));
 53.2287 -+
 53.2288 -+out:
 53.2289 -+	return segs;
 53.2290 -+}
 53.2291 -+
 53.2292 - extern void __skb_cb_too_small_for_tcp(int, int);
 53.2293 - extern struct tcp_congestion_ops tcp_reno;
 53.2294 - 
 53.2295 -diff -pruN ../orig-linux-2.6.16.29/net/ipv4/tcp_input.c ./net/ipv4/tcp_input.c
 53.2296 ---- ../orig-linux-2.6.16.29/net/ipv4/tcp_input.c	2006-09-12 19:02:10.000000000 +0100
 53.2297 -+++ ./net/ipv4/tcp_input.c	2006-09-19 13:59:20.000000000 +0100
 53.2298 -@@ -1072,7 +1072,7 @@ tcp_sacktag_write_queue(struct sock *sk,
 53.2299 - 				else
 53.2300 - 					pkt_len = (end_seq -
 53.2301 - 						   TCP_SKB_CB(skb)->seq);
 53.2302 --				if (tcp_fragment(sk, skb, pkt_len, skb_shinfo(skb)->tso_size))
 53.2303 -+				if (tcp_fragment(sk, skb, pkt_len, skb_shinfo(skb)->gso_size))
 53.2304 - 					break;
 53.2305 - 				pcount = tcp_skb_pcount(skb);
 53.2306 - 			}
 53.2307 -diff -pruN ../orig-linux-2.6.16.29/net/ipv4/tcp_output.c ./net/ipv4/tcp_output.c
 53.2308 ---- ../orig-linux-2.6.16.29/net/ipv4/tcp_output.c	2006-09-12 19:02:10.000000000 +0100
 53.2309 -+++ ./net/ipv4/tcp_output.c	2006-09-19 13:59:20.000000000 +0100
 53.2310 -@@ -497,15 +497,17 @@ static void tcp_set_skb_tso_segs(struct 
 53.2311 - 		/* Avoid the costly divide in the normal
 53.2312 - 		 * non-TSO case.
 53.2313 - 		 */
 53.2314 --		skb_shinfo(skb)->tso_segs = 1;
 53.2315 --		skb_shinfo(skb)->tso_size = 0;
 53.2316 -+		skb_shinfo(skb)->gso_segs = 1;
 53.2317 -+		skb_shinfo(skb)->gso_size = 0;
 53.2318 -+		skb_shinfo(skb)->gso_type = 0;
 53.2319 - 	} else {
 53.2320 - 		unsigned int factor;
 53.2321 - 
 53.2322 - 		factor = skb->len + (mss_now - 1);
 53.2323 - 		factor /= mss_now;
 53.2324 --		skb_shinfo(skb)->tso_segs = factor;
 53.2325 --		skb_shinfo(skb)->tso_size = mss_now;
 53.2326 -+		skb_shinfo(skb)->gso_segs = factor;
 53.2327 -+		skb_shinfo(skb)->gso_size = mss_now;
 53.2328 -+		skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
 53.2329 - 	}
 53.2330 - }
 53.2331 - 
 53.2332 -@@ -850,7 +852,7 @@ static int tcp_init_tso_segs(struct sock
 53.2333 - 
 53.2334 - 	if (!tso_segs ||
 53.2335 - 	    (tso_segs > 1 &&
 53.2336 --	     skb_shinfo(skb)->tso_size != mss_now)) {
 53.2337 -+	     tcp_skb_mss(skb) != mss_now)) {
 53.2338 - 		tcp_set_skb_tso_segs(sk, skb, mss_now);
 53.2339 - 		tso_segs = tcp_skb_pcount(skb);
 53.2340 - 	}
 53.2341 -@@ -1510,8 +1512,9 @@ int tcp_retransmit_skb(struct sock *sk, 
 53.2342 - 	   tp->snd_una == (TCP_SKB_CB(skb)->end_seq - 1)) {
 53.2343 - 		if (!pskb_trim(skb, 0)) {
 53.2344 - 			TCP_SKB_CB(skb)->seq = TCP_SKB_CB(skb)->end_seq - 1;
 53.2345 --			skb_shinfo(skb)->tso_segs = 1;
 53.2346 --			skb_shinfo(skb)->tso_size = 0;
 53.2347 -+			skb_shinfo(skb)->gso_segs = 1;
 53.2348 -+			skb_shinfo(skb)->gso_size = 0;
 53.2349 -+			skb_shinfo(skb)->gso_type = 0;
 53.2350 - 			skb->ip_summed = CHECKSUM_NONE;
 53.2351 - 			skb->csum = 0;
 53.2352 - 		}
 53.2353 -@@ -1716,8 +1719,9 @@ void tcp_send_fin(struct sock *sk)
 53.2354 - 		skb->csum = 0;
 53.2355 - 		TCP_SKB_CB(skb)->flags = (TCPCB_FLAG_ACK | TCPCB_FLAG_FIN);
 53.2356 - 		TCP_SKB_CB(skb)->sacked = 0;
 53.2357 --		skb_shinfo(skb)->tso_segs = 1;
 53.2358 --		skb_shinfo(skb)->tso_size = 0;
 53.2359 -+		skb_shinfo(skb)->gso_segs = 1;
 53.2360 -+		skb_shinfo(skb)->gso_size = 0;
 53.2361 -+		skb_shinfo(skb)->gso_type = 0;
 53.2362 - 
 53.2363 - 		/* FIN eats a sequence byte, write_seq advanced by tcp_queue_skb(). */
 53.2364 - 		TCP_SKB_CB(skb)->seq = tp->write_seq;
 53.2365 -@@ -1749,8 +1753,9 @@ void tcp_send_active_reset(struct sock *
 53.2366 - 	skb->csum = 0;
 53.2367 - 	TCP_SKB_CB(skb)->flags = (TCPCB_FLAG_ACK | TCPCB_FLAG_RST);
 53.2368 - 	TCP_SKB_CB(skb)->sacked = 0;
 53.2369 --	skb_shinfo(skb)->tso_segs = 1;
 53.2370 --	skb_shinfo(skb)->tso_size = 0;
 53.2371 -+	skb_shinfo(skb)->gso_segs = 1;
 53.2372 -+	skb_shinfo(skb)->gso_size = 0;
 53.2373 -+	skb_shinfo(skb)->gso_type = 0;
 53.2374 - 
 53.2375 - 	/* Send it off. */
 53.2376 - 	TCP_SKB_CB(skb)->seq = tcp_acceptable_seq(sk, tp);
 53.2377 -@@ -1833,8 +1838,9 @@ struct sk_buff * tcp_make_synack(struct 
 53.2378 - 	TCP_SKB_CB(skb)->seq = tcp_rsk(req)->snt_isn;
 53.2379 - 	TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(skb)->seq + 1;
 53.2380 - 	TCP_SKB_CB(skb)->sacked = 0;
 53.2381 --	skb_shinfo(skb)->tso_segs = 1;
 53.2382 --	skb_shinfo(skb)->tso_size = 0;
 53.2383 -+	skb_shinfo(skb)->gso_segs = 1;
 53.2384 -+	skb_shinfo(skb)->gso_size = 0;
 53.2385 -+	skb_shinfo(skb)->gso_type = 0;
 53.2386 - 	th->seq = htonl(TCP_SKB_CB(skb)->seq);
 53.2387 - 	th->ack_seq = htonl(tcp_rsk(req)->rcv_isn + 1);
 53.2388 - 	if (req->rcv_wnd == 0) { /* ignored for retransmitted syns */
 53.2389 -@@ -1937,8 +1943,9 @@ int tcp_connect(struct sock *sk)
 53.2390 - 	TCP_SKB_CB(buff)->flags = TCPCB_FLAG_SYN;
 53.2391 - 	TCP_ECN_send_syn(sk, tp, buff);
 53.2392 - 	TCP_SKB_CB(buff)->sacked = 0;
 53.2393 --	skb_shinfo(buff)->tso_segs = 1;
 53.2394 --	skb_shinfo(buff)->tso_size = 0;
 53.2395 -+	skb_shinfo(buff)->gso_segs = 1;
 53.2396 -+	skb_shinfo(buff)->gso_size = 0;
 53.2397 -+	skb_shinfo(buff)->gso_type = 0;
 53.2398 - 	buff->csum = 0;
 53.2399 - 	TCP_SKB_CB(buff)->seq = tp->write_seq++;
 53.2400 - 	TCP_SKB_CB(buff)->end_seq = tp->write_seq;
 53.2401 -@@ -2042,8 +2049,9 @@ void tcp_send_ack(struct sock *sk)
 53.2402 - 		buff->csum = 0;
 53.2403 - 		TCP_SKB_CB(buff)->flags = TCPCB_FLAG_ACK;
 53.2404 - 		TCP_SKB_CB(buff)->sacked = 0;
 53.2405 --		skb_shinfo(buff)->tso_segs = 1;
 53.2406 --		skb_shinfo(buff)->tso_size = 0;
 53.2407 -+		skb_shinfo(buff)->gso_segs = 1;
 53.2408 -+		skb_shinfo(buff)->gso_size = 0;
 53.2409 -+		skb_shinfo(buff)->gso_type = 0;
 53.2410 - 
 53.2411 - 		/* Send it off, this clears delayed acks for us. */
 53.2412 - 		TCP_SKB_CB(buff)->seq = TCP_SKB_CB(buff)->end_seq = tcp_acceptable_seq(sk, tp);
 53.2413 -@@ -2078,8 +2086,9 @@ static int tcp_xmit_probe_skb(struct soc
 53.2414 - 	skb->csum = 0;
 53.2415 - 	TCP_SKB_CB(skb)->flags = TCPCB_FLAG_ACK;
 53.2416 - 	TCP_SKB_CB(skb)->sacked = urgent;
 53.2417 --	skb_shinfo(skb)->tso_segs = 1;
 53.2418 --	skb_shinfo(skb)->tso_size = 0;
 53.2419 -+	skb_shinfo(skb)->gso_segs = 1;
 53.2420 -+	skb_shinfo(skb)->gso_size = 0;
 53.2421 -+	skb_shinfo(skb)->gso_type = 0;
 53.2422 - 
 53.2423 - 	/* Use a previous sequence.  This should cause the other
 53.2424 - 	 * end to send an ack.  Don't queue or clone SKB, just
 53.2425 -diff -pruN ../orig-linux-2.6.16.29/net/ipv4/xfrm4_output.c ./net/ipv4/xfrm4_output.c
 53.2426 ---- ../orig-linux-2.6.16.29/net/ipv4/xfrm4_output.c	2006-09-19 13:59:15.000000000 +0100
 53.2427 -+++ ./net/ipv4/xfrm4_output.c	2006-09-19 13:59:20.000000000 +0100
 53.2428 -@@ -9,6 +9,8 @@
 53.2429 -  */
 53.2430 - 
 53.2431 - #include <linux/compiler.h>
 53.2432 -+#include <linux/if_ether.h>
 53.2433 -+#include <linux/kernel.h>
 53.2434 - #include <linux/skbuff.h>
 53.2435 - #include <linux/spinlock.h>
 53.2436 - #include <linux/netfilter_ipv4.h>
 53.2437 -@@ -158,16 +160,10 @@ error_nolock:
 53.2438 - 	goto out_exit;
 53.2439 - }
 53.2440 - 
 53.2441 --static int xfrm4_output_finish(struct sk_buff *skb)
 53.2442 -+static int xfrm4_output_finish2(struct sk_buff *skb)
 53.2443 - {
 53.2444 - 	int err;
 53.2445 - 
 53.2446 --#ifdef CONFIG_NETFILTER
 53.2447 --	if (!skb->dst->xfrm) {
 53.2448 --		IPCB(skb)->flags |= IPSKB_REROUTED;
 53.2449 --		return dst_output(skb);
 53.2450 --	}
 53.2451 --#endif
 53.2452 - 	while (likely((err = xfrm4_output_one(skb)) == 0)) {
 53.2453 - 		nf_reset(skb);
 53.2454 - 
 53.2455 -@@ -180,7 +176,7 @@ static int xfrm4_output_finish(struct sk
 53.2456 - 			return dst_output(skb);
 53.2457 - 
 53.2458 - 		err = nf_hook(PF_INET, NF_IP_POST_ROUTING, &skb, NULL,
 53.2459 --			      skb->dst->dev, xfrm4_output_finish);
 53.2460 -+			      skb->dst->dev, xfrm4_output_finish2);
 53.2461 - 		if (unlikely(err != 1))
 53.2462 - 			break;
 53.2463 - 	}
 53.2464 -@@ -188,6 +184,48 @@ static int xfrm4_output_finish(struct sk
 53.2465 - 	return err;
 53.2466 - }
 53.2467 - 
 53.2468 -+static int xfrm4_output_finish(struct sk_buff *skb)
 53.2469 -+{
 53.2470 -+	struct sk_buff *segs;
 53.2471 -+
 53.2472 -+#ifdef CONFIG_NETFILTER
 53.2473 -+	if (!skb->dst->xfrm) {
 53.2474 -+		IPCB(skb)->flags |= IPSKB_REROUTED;
 53.2475 -+		return dst_output(skb);
 53.2476 -+	}
 53.2477 -+#endif
 53.2478 -+
 53.2479 -+	if (!skb_shinfo(skb)->gso_size)
 53.2480 -+		return xfrm4_output_finish2(skb);
 53.2481 -+
 53.2482 -+	skb->protocol = htons(ETH_P_IP);
 53.2483 -+	segs = skb_gso_segment(skb, 0);
 53.2484 -+	kfree_skb(skb);
 53.2485 -+	if (unlikely(IS_ERR(segs)))
 53.2486 -+		return PTR_ERR(segs);
 53.2487 -+
 53.2488 -+	do {
 53.2489 -+		struct sk_buff *nskb = segs->next;
 53.2490 -+		int err;
 53.2491 -+
 53.2492 -+		segs->next = NULL;
 53.2493 -+		err = xfrm4_output_finish2(segs);
 53.2494 -+
 53.2495 -+		if (unlikely(err)) {
 53.2496 -+			while ((segs = nskb)) {
 53.2497 -+				nskb = segs->next;
 53.2498 -+				segs->next = NULL;
 53.2499 -+				kfree_skb(segs);
 53.2500 -+			}
 53.2501 -+			return err;
 53.2502 -+		}
 53.2503 -+
 53.2504 -+		segs = nskb;
 53.2505 -+	} while (segs);
 53.2506 -+
 53.2507 -+	return 0;
 53.2508 -+}
 53.2509 -+
 53.2510 - int xfrm4_output(struct sk_buff *skb)
 53.2511 - {
 53.2512 - 	return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL, skb->dst->dev,
 53.2513 -diff -pruN ../orig-linux-2.6.16.29/net/ipv6/ip6_output.c ./net/ipv6/ip6_output.c
 53.2514 ---- ../orig-linux-2.6.16.29/net/ipv6/ip6_output.c	2006-09-12 19:02:10.000000000 +0100
 53.2515 -+++ ./net/ipv6/ip6_output.c	2006-09-19 13:59:20.000000000 +0100
 53.2516 -@@ -147,7 +147,7 @@ static int ip6_output2(struct sk_buff *s
 53.2517 - 
 53.2518 - int ip6_output(struct sk_buff *skb)
 53.2519 - {
 53.2520 --	if ((skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->ufo_size) ||
 53.2521 -+	if ((skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->gso_size) ||
 53.2522 - 				dst_allfrag(skb->dst))
 53.2523 - 		return ip6_fragment(skb, ip6_output2);
 53.2524 - 	else
 53.2525 -@@ -829,8 +829,9 @@ static inline int ip6_ufo_append_data(st
 53.2526 - 		struct frag_hdr fhdr;
 53.2527 - 
 53.2528 - 		/* specify the length of each IP datagram fragment*/
 53.2529 --		skb_shinfo(skb)->ufo_size = (mtu - fragheaderlen) - 
 53.2530 --						sizeof(struct frag_hdr);
 53.2531 -+		skb_shinfo(skb)->gso_size = mtu - fragheaderlen - 
 53.2532 -+					    sizeof(struct frag_hdr);
 53.2533 -+		skb_shinfo(skb)->gso_type = SKB_GSO_UDPV4;
 53.2534 - 		ipv6_select_ident(skb, &fhdr);
 53.2535 - 		skb_shinfo(skb)->ip6_frag_id = fhdr.identification;
 53.2536 - 		__skb_queue_tail(&sk->sk_write_queue, skb);
 53.2537 -diff -pruN ../orig-linux-2.6.16.29/net/ipv6/ipcomp6.c ./net/ipv6/ipcomp6.c
 53.2538 ---- ../orig-linux-2.6.16.29/net/ipv6/ipcomp6.c	2006-09-12 19:02:10.000000000 +0100
 53.2539 -+++ ./net/ipv6/ipcomp6.c	2006-09-19 13:59:20.000000000 +0100
 53.2540 -@@ -64,7 +64,7 @@ static LIST_HEAD(ipcomp6_tfms_list);
 53.2541 - 
 53.2542 - static int ipcomp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
 53.2543 - {
 53.2544 --	int err = 0;
 53.2545 -+	int err = -ENOMEM;
 53.2546 - 	u8 nexthdr = 0;
 53.2547 - 	int hdr_len = skb->h.raw - skb->nh.raw;
 53.2548 - 	unsigned char *tmp_hdr = NULL;
 53.2549 -@@ -75,11 +75,8 @@ static int ipcomp6_input(struct xfrm_sta
 53.2550 - 	struct crypto_tfm *tfm;
 53.2551 - 	int cpu;
 53.2552 - 
 53.2553 --	if ((skb_is_nonlinear(skb) || skb_cloned(skb)) &&
 53.2554 --		skb_linearize(skb, GFP_ATOMIC) != 0) {
 53.2555 --		err = -ENOMEM;
 53.2556 -+	if (skb_linearize_cow(skb))
 53.2557 - 		goto out;
 53.2558 --	}
 53.2559 - 
 53.2560 - 	skb->ip_summed = CHECKSUM_NONE;
 53.2561 - 
 53.2562 -@@ -158,10 +155,8 @@ static int ipcomp6_output(struct xfrm_st
 53.2563 - 		goto out_ok;
 53.2564 - 	}
 53.2565 - 
 53.2566 --	if ((skb_is_nonlinear(skb) || skb_cloned(skb)) &&
 53.2567 --		skb_linearize(skb, GFP_ATOMIC) != 0) {
 53.2568 -+	if (skb_linearize_cow(skb))
 53.2569 - 		goto out_ok;
 53.2570 --	}
 53.2571 - 
 53.2572 - 	/* compression */
 53.2573 - 	plen = skb->len - hdr_len;
 53.2574 -diff -pruN ../orig-linux-2.6.16.29/net/ipv6/xfrm6_output.c ./net/ipv6/xfrm6_output.c
 53.2575 ---- ../orig-linux-2.6.16.29/net/ipv6/xfrm6_output.c	2006-09-12 19:02:10.000000000 +0100
 53.2576 -+++ ./net/ipv6/xfrm6_output.c	2006-09-19 13:59:20.000000000 +0100
 53.2577 -@@ -151,7 +151,7 @@ error_nolock:
 53.2578 - 	goto out_exit;
 53.2579 - }
 53.2580 - 
 53.2581 --static int xfrm6_output_finish(struct sk_buff *skb)
 53.2582 -+static int xfrm6_output_finish2(struct sk_buff *skb)
 53.2583 - {
 53.2584 - 	int err;
 53.2585 - 
 53.2586 -@@ -167,7 +167,7 @@ static int xfrm6_output_finish(struct sk
 53.2587 - 			return dst_output(skb);
 53.2588 - 
 53.2589 - 		err = nf_hook(PF_INET6, NF_IP6_POST_ROUTING, &skb, NULL,
 53.2590 --			      skb->dst->dev, xfrm6_output_finish);
 53.2591 -+			      skb->dst->dev, xfrm6_output_finish2);
 53.2592 - 		if (unlikely(err != 1))
 53.2593 - 			break;
 53.2594 - 	}
 53.2595 -@@ -175,6 +175,41 @@ static int xfrm6_output_finish(struct sk
 53.2596 - 	return err;
 53.2597 - }
 53.2598 - 
 53.2599 -+static int xfrm6_output_finish(struct sk_buff *skb)
 53.2600 -+{
 53.2601 -+	struct sk_buff *segs;
 53.2602 -+
 53.2603 -+	if (!skb_shinfo(skb)->gso_size)
 53.2604 -+		return xfrm6_output_finish2(skb);
 53.2605 -+
 53.2606 -+	skb->protocol = htons(ETH_P_IP);
 53.2607 -+	segs = skb_gso_segment(skb, 0);
 53.2608 -+	kfree_skb(skb);
 53.2609 -+	if (unlikely(IS_ERR(segs)))
 53.2610 -+		return PTR_ERR(segs);
 53.2611 -+
 53.2612 -+	do {
 53.2613 -+		struct sk_buff *nskb = segs->next;
 53.2614 -+		int err;
 53.2615 -+
 53.2616 -+		segs->next = NULL;
 53.2617 -+		err = xfrm6_output_finish2(segs);
 53.2618 -+
 53.2619 -+		if (unlikely(err)) {
 53.2620 -+			while ((segs = nskb)) {
 53.2621 -+				nskb = segs->next;
 53.2622 -+				segs->next = NULL;
 53.2623 -+				kfree_skb(segs);
 53.2624 -+			}
 53.2625 -+			return err;
 53.2626 -+		}
 53.2627 -+
 53.2628 -+		segs = nskb;
 53.2629 -+	} while (segs);
 53.2630 -+
 53.2631 -+	return 0;
 53.2632 -+}
 53.2633 -+
 53.2634 - int xfrm6_output(struct sk_buff *skb)
 53.2635 - {
 53.2636 - 	return NF_HOOK(PF_INET6, NF_IP6_POST_ROUTING, skb, NULL, skb->dst->dev,
 53.2637 -diff -pruN ../orig-linux-2.6.16.29/net/sched/sch_generic.c ./net/sched/sch_generic.c
 53.2638 ---- ../orig-linux-2.6.16.29/net/sched/sch_generic.c	2006-09-12 19:02:10.000000000 +0100
 53.2639 -+++ ./net/sched/sch_generic.c	2006-09-19 13:59:20.000000000 +0100
 53.2640 -@@ -72,9 +72,9 @@ void qdisc_unlock_tree(struct net_device
 53.2641 -    dev->queue_lock serializes queue accesses for this device
 53.2642 -    AND dev->qdisc pointer itself.
 53.2643 - 
 53.2644 --   dev->xmit_lock serializes accesses to device driver.
 53.2645 -+   netif_tx_lock serializes accesses to device driver.
 53.2646 - 
 53.2647 --   dev->queue_lock and dev->xmit_lock are mutually exclusive,
 53.2648 -+   dev->queue_lock and netif_tx_lock are mutually exclusive,
 53.2649 -    if one is grabbed, another must be free.
 53.2650 -  */
 53.2651 - 
 53.2652 -@@ -90,14 +90,17 @@ void qdisc_unlock_tree(struct net_device
 53.2653 -    NOTE: Called under dev->queue_lock with locally disabled BH.
 53.2654 - */
 53.2655 - 
 53.2656 --int qdisc_restart(struct net_device *dev)
 53.2657 -+static inline int qdisc_restart(struct net_device *dev)
 53.2658 - {
 53.2659 - 	struct Qdisc *q = dev->qdisc;
 53.2660 - 	struct sk_buff *skb;
 53.2661 - 
 53.2662 - 	/* Dequeue packet */
 53.2663 --	if ((skb = q->dequeue(q)) != NULL) {
 53.2664 -+	if (((skb = dev->gso_skb)) || ((skb = q->dequeue(q)))) {
 53.2665 - 		unsigned nolock = (dev->features & NETIF_F_LLTX);
 53.2666 -+
 53.2667 -+		dev->gso_skb = NULL;
 53.2668 -+
 53.2669 - 		/*
 53.2670 - 		 * When the driver has LLTX set it does its own locking
 53.2671 - 		 * in start_xmit. No need to add additional overhead by
 53.2672 -@@ -108,7 +111,7 @@ int qdisc_restart(struct net_device *dev
 53.2673 - 		 * will be requeued.
 53.2674 - 		 */
 53.2675 - 		if (!nolock) {
 53.2676 --			if (!spin_trylock(&dev->xmit_lock)) {
 53.2677 -+			if (!netif_tx_trylock(dev)) {
 53.2678 - 			collision:
 53.2679 - 				/* So, someone grabbed the driver. */
 53.2680 - 				
 53.2681 -@@ -126,8 +129,6 @@ int qdisc_restart(struct net_device *dev
 53.2682 - 				__get_cpu_var(netdev_rx_stat).cpu_collision++;
 53.2683 - 				goto requeue;
 53.2684 - 			}
 53.2685 --			/* Remember that the driver is grabbed by us. */
 53.2686 --			dev->xmit_lock_owner = smp_processor_id();
 53.2687 - 		}
 53.2688 - 		
 53.2689 - 		{
 53.2690 -@@ -136,14 +137,11 @@ int qdisc_restart(struct net_device *dev
 53.2691 - 
 53.2692 - 			if (!netif_queue_stopped(dev)) {
 53.2693 - 				int ret;
 53.2694 --				if (netdev_nit)
 53.2695 --					dev_queue_xmit_nit(skb, dev);
 53.2696 - 
 53.2697 --				ret = dev->hard_start_xmit(skb, dev);
 53.2698 -+				ret = dev_hard_start_xmit(skb, dev);
 53.2699 - 				if (ret == NETDEV_TX_OK) { 
 53.2700 - 					if (!nolock) {
 53.2701 --						dev->xmit_lock_owner = -1;
 53.2702 --						spin_unlock(&dev->xmit_lock);
 53.2703 -+						netif_tx_unlock(dev);
 53.2704 - 					}
 53.2705 - 					spin_lock(&dev->queue_lock);
 53.2706 - 					return -1;
 53.2707 -@@ -157,8 +155,7 @@ int qdisc_restart(struct net_device *dev
 53.2708 - 			/* NETDEV_TX_BUSY - we need to requeue */
 53.2709 - 			/* Release the driver */
 53.2710 - 			if (!nolock) { 
 53.2711 --				dev->xmit_lock_owner = -1;
 53.2712 --				spin_unlock(&dev->xmit_lock);
 53.2713 -+				netif_tx_unlock(dev);
 53.2714 - 			} 
 53.2715 - 			spin_lock(&dev->queue_lock);
 53.2716 - 			q = dev->qdisc;
 53.2717 -@@ -175,7 +172,10 @@ int qdisc_restart(struct net_device *dev
 53.2718 - 		 */
 53.2719 - 
 53.2720 - requeue:
 53.2721 --		q->ops->requeue(skb, q);
 53.2722 -+		if (skb->next)
 53.2723 -+			dev->gso_skb = skb;
 53.2724 -+		else
 53.2725 -+			q->ops->requeue(skb, q);
 53.2726 - 		netif_schedule(dev);
 53.2727 - 		return 1;
 53.2728 - 	}
 53.2729 -@@ -183,11 +183,23 @@ requeue:
 53.2730 - 	return q->q.qlen;
 53.2731 - }
 53.2732 - 
 53.2733 -+void __qdisc_run(struct net_device *dev)
 53.2734 -+{
 53.2735 -+	if (unlikely(dev->qdisc == &noop_qdisc))
 53.2736 -+		goto out;
 53.2737 -+
 53.2738 -+	while (qdisc_restart(dev) < 0 && !netif_queue_stopped(dev))
 53.2739 -+		/* NOTHING */;
 53.2740 -+
 53.2741 -+out:
 53.2742 -+	clear_bit(__LINK_STATE_QDISC_RUNNING, &dev->state);
 53.2743 -+}
 53.2744 -+
 53.2745 - static void dev_watchdog(unsigned long arg)
 53.2746 - {
 53.2747 - 	struct net_device *dev = (struct net_device *)arg;
 53.2748 - 
 53.2749 --	spin_lock(&dev->xmit_lock);
 53.2750 -+	netif_tx_lock(dev);
 53.2751 - 	if (dev->qdisc != &noop_qdisc) {
 53.2752 - 		if (netif_device_present(dev) &&
 53.2753 - 		    netif_running(dev) &&
 53.2754 -@@ -201,7 +213,7 @@ static void dev_watchdog(unsigned long a
 53.2755 - 				dev_hold(dev);
 53.2756 - 		}
 53.2757 - 	}
 53.2758 --	spin_unlock(&dev->xmit_lock);
 53.2759 -+	netif_tx_unlock(dev);
 53.2760 - 
 53.2761 - 	dev_put(dev);
 53.2762 - }
 53.2763 -@@ -225,17 +237,17 @@ void __netdev_watchdog_up(struct net_dev
 53.2764 - 
 53.2765 - static void dev_watchdog_up(struct net_device *dev)
 53.2766 - {
 53.2767 --	spin_lock_bh(&dev->xmit_lock);
 53.2768 -+	netif_tx_lock_bh(dev);
 53.2769 - 	__netdev_watchdog_up(dev);
 53.2770 --	spin_unlock_bh(&dev->xmit_lock);
 53.2771 -+	netif_tx_unlock_bh(dev);
 53.2772 - }
 53.2773 - 
 53.2774 - static void dev_watchdog_down(struct net_device *dev)
 53.2775 - {
 53.2776 --	spin_lock_bh(&dev->xmit_lock);
 53.2777 -+	netif_tx_lock_bh(dev);
 53.2778 - 	if (del_timer(&dev->watchdog_timer))
 53.2779 - 		__dev_put(dev);
 53.2780 --	spin_unlock_bh(&dev->xmit_lock);
 53.2781 -+	netif_tx_unlock_bh(dev);
 53.2782 - }
 53.2783 - 
 53.2784 - void netif_carrier_on(struct net_device *dev)
 53.2785 -@@ -577,10 +589,17 @@ void dev_deactivate(struct net_device *d
 53.2786 - 
 53.2787 - 	dev_watchdog_down(dev);
 53.2788 - 
 53.2789 --	while (test_bit(__LINK_STATE_SCHED, &dev->state))
 53.2790 -+	/* Wait for outstanding dev_queue_xmit calls. */
 53.2791 -+	synchronize_rcu();
 53.2792 -+
 53.2793 -+	/* Wait for outstanding qdisc_run calls. */
 53.2794 -+	while (test_bit(__LINK_STATE_QDISC_RUNNING, &dev->state))
 53.2795 - 		yield();
 53.2796 - 
 53.2797 --	spin_unlock_wait(&dev->xmit_lock);
 53.2798 -+	if (dev->gso_skb) {
 53.2799 -+		kfree_skb(dev->gso_skb);
 53.2800 -+		dev->gso_skb = NULL;
 53.2801 -+	}
 53.2802 - }
 53.2803 - 
 53.2804 - void dev_init_scheduler(struct net_device *dev)
 53.2805 -@@ -622,6 +641,5 @@ EXPORT_SYMBOL(qdisc_create_dflt);
 53.2806 - EXPORT_SYMBOL(qdisc_alloc);
 53.2807 - EXPORT_SYMBOL(qdisc_destroy);
 53.2808 - EXPORT_SYMBOL(qdisc_reset);
 53.2809 --EXPORT_SYMBOL(qdisc_restart);
 53.2810 - EXPORT_SYMBOL(qdisc_lock_tree);
 53.2811 - EXPORT_SYMBOL(qdisc_unlock_tree);
 53.2812 -diff -pruN ../orig-linux-2.6.16.29/net/sched/sch_teql.c ./net/sched/sch_teql.c
 53.2813 ---- ../orig-linux-2.6.16.29/net/sched/sch_teql.c	2006-09-12 19:02:10.000000000 +0100
 53.2814 -+++ ./net/sched/sch_teql.c	2006-09-19 13:59:20.000000000 +0100
 53.2815 -@@ -302,20 +302,17 @@ restart:
 53.2816 - 
 53.2817 - 		switch (teql_resolve(skb, skb_res, slave)) {
 53.2818 - 		case 0:
 53.2819 --			if (spin_trylock(&slave->xmit_lock)) {
 53.2820 --				slave->xmit_lock_owner = smp_processor_id();
 53.2821 -+			if (netif_tx_trylock(slave)) {
 53.2822 - 				if (!netif_queue_stopped(slave) &&
 53.2823 - 				    slave->hard_start_xmit(skb, slave) == 0) {
 53.2824 --					slave->xmit_lock_owner = -1;
 53.2825 --					spin_unlock(&slave->xmit_lock);
 53.2826 -+					netif_tx_unlock(slave);
 53.2827 - 					master->slaves = NEXT_SLAVE(q);
 53.2828 - 					netif_wake_queue(dev);
 53.2829 - 					master->stats.tx_packets++;
 53.2830 - 					master->stats.tx_bytes += len;
 53.2831 - 					return 0;
 53.2832 - 				}
 53.2833 --				slave->xmit_lock_owner = -1;
 53.2834 --				spin_unlock(&slave->xmit_lock);
 53.2835 -+				netif_tx_unlock(slave);
 53.2836 - 			}
 53.2837 - 			if (netif_queue_stopped(dev))
 53.2838 - 				busy = 1;
    54.1 --- a/patches/linux-2.6.16.29/net-gso-1-check-dodgy.patch	Mon Nov 27 10:10:57 2006 -0700
    54.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    54.3 @@ -1,27 +0,0 @@
    54.4 -diff -pruN ../orig-linux-2.6.16.29/net/ipv4/tcp.c ./net/ipv4/tcp.c
    54.5 ---- ../orig-linux-2.6.16.29/net/ipv4/tcp.c	2006-09-19 13:59:20.000000000 +0100
    54.6 -+++ ./net/ipv4/tcp.c	2006-09-19 13:59:42.000000000 +0100
    54.7 -@@ -2042,13 +2042,19 @@ struct sk_buff *tcp_tso_segment(struct s
    54.8 - 	if (!pskb_may_pull(skb, thlen))
    54.9 - 		goto out;
   54.10 - 
   54.11 --	segs = NULL;
   54.12 --	if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST))
   54.13 --		goto out;
   54.14 --
   54.15 - 	oldlen = (u16)~skb->len;
   54.16 - 	__skb_pull(skb, thlen);
   54.17 - 
   54.18 -+	if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) {
   54.19 -+		/* Packet is from an untrusted source, reset gso_segs. */
   54.20 -+		int mss = skb_shinfo(skb)->gso_size;
   54.21 -+
   54.22 -+		skb_shinfo(skb)->gso_segs = (skb->len + mss - 1) / mss;
   54.23 -+
   54.24 -+		segs = NULL;
   54.25 -+		goto out;
   54.26 -+	}
   54.27 -+
   54.28 - 	segs = skb_segment(skb, features);
   54.29 - 	if (IS_ERR(segs))
   54.30 - 		goto out;
    55.1 --- a/patches/linux-2.6.16.29/net-gso-2-checksum-fix.patch	Mon Nov 27 10:10:57 2006 -0700
    55.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    55.3 @@ -1,451 +0,0 @@
    55.4 -diff -pruN ../orig-linux-2.6.16.29/drivers/net/bnx2.c ./drivers/net/bnx2.c
    55.5 ---- ../orig-linux-2.6.16.29/drivers/net/bnx2.c	2006-09-19 13:59:20.000000000 +0100
    55.6 -+++ ./drivers/net/bnx2.c	2006-09-19 13:59:46.000000000 +0100
    55.7 -@@ -1593,7 +1593,7 @@ bnx2_tx_int(struct bnx2 *bp)
    55.8 - 		skb = tx_buf->skb;
    55.9 - #ifdef BCM_TSO 
   55.10 - 		/* partial BD completions possible with TSO packets */
   55.11 --		if (skb_shinfo(skb)->gso_size) {
   55.12 -+		if (skb_is_gso(skb)) {
   55.13 - 			u16 last_idx, last_ring_idx;
   55.14 - 
   55.15 - 			last_idx = sw_cons +
   55.16 -diff -pruN ../orig-linux-2.6.16.29/drivers/net/chelsio/sge.c ./drivers/net/chelsio/sge.c
   55.17 ---- ../orig-linux-2.6.16.29/drivers/net/chelsio/sge.c	2006-09-19 13:59:20.000000000 +0100
   55.18 -+++ ./drivers/net/chelsio/sge.c	2006-09-19 13:59:46.000000000 +0100
   55.19 -@@ -1419,7 +1419,7 @@ int t1_start_xmit(struct sk_buff *skb, s
   55.20 - 	struct cpl_tx_pkt *cpl;
   55.21 - 
   55.22 - #ifdef NETIF_F_TSO
   55.23 --	if (skb_shinfo(skb)->gso_size) {
   55.24 -+	if (skb_is_gso(skb)) {
   55.25 - 		int eth_type;
   55.26 - 		struct cpl_tx_pkt_lso *hdr;
   55.27 - 
   55.28 -diff -pruN ../orig-linux-2.6.16.29/drivers/net/e1000/e1000_main.c ./drivers/net/e1000/e1000_main.c
   55.29 ---- ../orig-linux-2.6.16.29/drivers/net/e1000/e1000_main.c	2006-09-19 13:59:20.000000000 +0100
   55.30 -+++ ./drivers/net/e1000/e1000_main.c	2006-09-19 13:59:46.000000000 +0100
   55.31 -@@ -2526,7 +2526,7 @@ e1000_tso(struct e1000_adapter *adapter,
   55.32 - 	uint8_t ipcss, ipcso, tucss, tucso, hdr_len;
   55.33 - 	int err;
   55.34 - 
   55.35 --	if (skb_shinfo(skb)->gso_size) {
   55.36 -+	if (skb_is_gso(skb)) {
   55.37 - 		if (skb_header_cloned(skb)) {
   55.38 - 			err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
   55.39 - 			if (err)
   55.40 -@@ -2651,7 +2651,7 @@ e1000_tx_map(struct e1000_adapter *adapt
   55.41 - 		 * tso gets written back prematurely before the data is fully
   55.42 - 		 * DMAd to the controller */
   55.43 - 		if (!skb->data_len && tx_ring->last_tx_tso &&
   55.44 --				!skb_shinfo(skb)->gso_size) {
   55.45 -+		    !skb_is_gso(skb)) {
   55.46 - 			tx_ring->last_tx_tso = 0;
   55.47 - 			size -= 4;
   55.48 - 		}
   55.49 -@@ -2934,8 +2934,7 @@ e1000_xmit_frame(struct sk_buff *skb, st
   55.50 - 
   55.51 - #ifdef NETIF_F_TSO
   55.52 - 	/* Controller Erratum workaround */
   55.53 --	if (!skb->data_len && tx_ring->last_tx_tso &&
   55.54 --		!skb_shinfo(skb)->gso_size)
   55.55 -+	if (!skb->data_len && tx_ring->last_tx_tso && !skb_is_gso(skb))
   55.56 - 		count++;
   55.57 - #endif
   55.58 - 
   55.59 -diff -pruN ../orig-linux-2.6.16.29/drivers/net/forcedeth.c ./drivers/net/forcedeth.c
   55.60 ---- ../orig-linux-2.6.16.29/drivers/net/forcedeth.c	2006-09-19 13:59:20.000000000 +0100
   55.61 -+++ ./drivers/net/forcedeth.c	2006-09-19 13:59:46.000000000 +0100
   55.62 -@@ -1105,7 +1105,7 @@ static int nv_start_xmit(struct sk_buff 
   55.63 - 	np->tx_skbuff[nr] = skb;
   55.64 - 
   55.65 - #ifdef NETIF_F_TSO
   55.66 --	if (skb_shinfo(skb)->gso_size)
   55.67 -+	if (skb_is_gso(skb))
   55.68 - 		tx_flags_extra = NV_TX2_TSO | (skb_shinfo(skb)->gso_size << NV_TX2_TSO_SHIFT);
   55.69 - 	else
   55.70 - #endif
   55.71 -diff -pruN ../orig-linux-2.6.16.29/drivers/net/ixgb/ixgb_main.c ./drivers/net/ixgb/ixgb_main.c
   55.72 ---- ../orig-linux-2.6.16.29/drivers/net/ixgb/ixgb_main.c	2006-09-19 13:59:20.000000000 +0100
   55.73 -+++ ./drivers/net/ixgb/ixgb_main.c	2006-09-19 13:59:46.000000000 +0100
   55.74 -@@ -1163,7 +1163,7 @@ ixgb_tso(struct ixgb_adapter *adapter, s
   55.75 - 	uint16_t ipcse, tucse, mss;
   55.76 - 	int err;
   55.77 - 
   55.78 --	if(likely(skb_shinfo(skb)->gso_size)) {
   55.79 -+	if (likely(skb_is_gso(skb))) {
   55.80 - 		if (skb_header_cloned(skb)) {
   55.81 - 			err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
   55.82 - 			if (err)
   55.83 -diff -pruN ../orig-linux-2.6.16.29/drivers/net/loopback.c ./drivers/net/loopback.c
   55.84 ---- ../orig-linux-2.6.16.29/drivers/net/loopback.c	2006-09-19 13:59:20.000000000 +0100
   55.85 -+++ ./drivers/net/loopback.c	2006-09-19 13:59:46.000000000 +0100
   55.86 -@@ -139,7 +139,7 @@ static int loopback_xmit(struct sk_buff 
   55.87 - #endif
   55.88 - 
   55.89 - #ifdef LOOPBACK_TSO
   55.90 --	if (skb_shinfo(skb)->gso_size) {
   55.91 -+	if (skb_is_gso(skb)) {
   55.92 - 		BUG_ON(skb->protocol != htons(ETH_P_IP));
   55.93 - 		BUG_ON(skb->nh.iph->protocol != IPPROTO_TCP);
   55.94 - 
   55.95 -diff -pruN ../orig-linux-2.6.16.29/drivers/net/sky2.c ./drivers/net/sky2.c
   55.96 ---- ../orig-linux-2.6.16.29/drivers/net/sky2.c	2006-09-19 13:59:20.000000000 +0100
   55.97 -+++ ./drivers/net/sky2.c	2006-09-19 13:59:46.000000000 +0100
   55.98 -@@ -1125,7 +1125,7 @@ static unsigned tx_le_req(const struct s
   55.99 - 	count = sizeof(dma_addr_t) / sizeof(u32);
  55.100 - 	count += skb_shinfo(skb)->nr_frags * count;
  55.101 - 
  55.102 --	if (skb_shinfo(skb)->gso_size)
  55.103 -+	if (skb_is_gso(skb))
  55.104 - 		++count;
  55.105 - 
  55.106 - 	if (skb->ip_summed == CHECKSUM_HW)
  55.107 -diff -pruN ../orig-linux-2.6.16.29/drivers/net/typhoon.c ./drivers/net/typhoon.c
  55.108 ---- ../orig-linux-2.6.16.29/drivers/net/typhoon.c	2006-09-19 13:59:20.000000000 +0100
  55.109 -+++ ./drivers/net/typhoon.c	2006-09-19 13:59:46.000000000 +0100
  55.110 -@@ -805,7 +805,7 @@ typhoon_start_tx(struct sk_buff *skb, st
  55.111 - 	 * If problems develop with TSO, check this first.
  55.112 - 	 */
  55.113 - 	numDesc = skb_shinfo(skb)->nr_frags + 1;
  55.114 --	if(skb_tso_size(skb))
  55.115 -+	if (skb_is_gso(skb))
  55.116 - 		numDesc++;
  55.117 - 
  55.118 - 	/* When checking for free space in the ring, we need to also
  55.119 -@@ -845,7 +845,7 @@ typhoon_start_tx(struct sk_buff *skb, st
  55.120 - 				TYPHOON_TX_PF_VLAN_TAG_SHIFT);
  55.121 - 	}
  55.122 - 
  55.123 --	if(skb_tso_size(skb)) {
  55.124 -+	if (skb_is_gso(skb)) {
  55.125 - 		first_txd->processFlags |= TYPHOON_TX_PF_TCP_SEGMENT;
  55.126 - 		first_txd->numDesc++;
  55.127 - 
  55.128 -diff -pruN ../orig-linux-2.6.16.29/drivers/s390/net/qeth_main.c ./drivers/s390/net/qeth_main.c
  55.129 ---- ../orig-linux-2.6.16.29/drivers/s390/net/qeth_main.c	2006-09-19 13:59:20.000000000 +0100
  55.130 -+++ ./drivers/s390/net/qeth_main.c	2006-09-19 13:59:46.000000000 +0100
  55.131 -@@ -4454,7 +4454,7 @@ qeth_send_packet(struct qeth_card *card,
  55.132 - 	queue = card->qdio.out_qs
  55.133 - 		[qeth_get_priority_queue(card, skb, ipv, cast_type)];
  55.134 - 
  55.135 --	if (skb_shinfo(skb)->gso_size)
  55.136 -+	if (skb_is_gso(skb))
  55.137 - 		large_send = card->options.large_send;
  55.138 - 
  55.139 - 	/*are we able to do TSO ? If so ,prepare and send it from here */
  55.140 -@@ -4501,8 +4501,7 @@ qeth_send_packet(struct qeth_card *card,
  55.141 - 		card->stats.tx_packets++;
  55.142 - 		card->stats.tx_bytes += skb->len;
  55.143 - #ifdef CONFIG_QETH_PERF_STATS
  55.144 --		if (skb_shinfo(skb)->gso_size &&
  55.145 --		   !(large_send == QETH_LARGE_SEND_NO)) {
  55.146 -+		if (skb_is_gso(skb) && !(large_send == QETH_LARGE_SEND_NO)) {
  55.147 - 			card->perf_stats.large_send_bytes += skb->len;
  55.148 - 			card->perf_stats.large_send_cnt++;
  55.149 - 		}
  55.150 -diff -pruN ../orig-linux-2.6.16.29/include/linux/netdevice.h ./include/linux/netdevice.h
  55.151 ---- ../orig-linux-2.6.16.29/include/linux/netdevice.h	2006-09-19 13:59:20.000000000 +0100
  55.152 -+++ ./include/linux/netdevice.h	2006-09-19 13:59:46.000000000 +0100
  55.153 -@@ -541,6 +541,7 @@ struct packet_type {
  55.154 - 					 struct net_device *);
  55.155 - 	struct sk_buff		*(*gso_segment)(struct sk_buff *skb,
  55.156 - 						int features);
  55.157 -+	int			(*gso_send_check)(struct sk_buff *skb);
  55.158 - 	void			*af_packet_priv;
  55.159 - 	struct list_head	list;
  55.160 - };
  55.161 -@@ -1001,14 +1002,15 @@ extern void linkwatch_run_queue(void);
  55.162 - 
  55.163 - static inline int skb_gso_ok(struct sk_buff *skb, int features)
  55.164 - {
  55.165 --	int feature = skb_shinfo(skb)->gso_size ?
  55.166 --		      skb_shinfo(skb)->gso_type << NETIF_F_GSO_SHIFT : 0;
  55.167 -+	int feature = skb_shinfo(skb)->gso_type << NETIF_F_GSO_SHIFT;
  55.168 - 	return (features & feature) == feature;
  55.169 - }
  55.170 - 
  55.171 - static inline int netif_needs_gso(struct net_device *dev, struct sk_buff *skb)
  55.172 - {
  55.173 --	return !skb_gso_ok(skb, dev->features);
  55.174 -+	return skb_is_gso(skb) &&
  55.175 -+	       (!skb_gso_ok(skb, dev->features) ||
  55.176 -+		unlikely(skb->ip_summed != CHECKSUM_HW));
  55.177 - }
  55.178 - 
  55.179 - #endif /* __KERNEL__ */
  55.180 -diff -pruN ../orig-linux-2.6.16.29/include/linux/skbuff.h ./include/linux/skbuff.h
  55.181 ---- ../orig-linux-2.6.16.29/include/linux/skbuff.h	2006-09-19 13:59:20.000000000 +0100
  55.182 -+++ ./include/linux/skbuff.h	2006-09-19 13:59:46.000000000 +0100
  55.183 -@@ -1403,5 +1403,10 @@ static inline void nf_bridge_get(struct 
  55.184 - static inline void nf_reset(struct sk_buff *skb) {}
  55.185 - #endif /* CONFIG_NETFILTER */
  55.186 - 
  55.187 -+static inline int skb_is_gso(const struct sk_buff *skb)
  55.188 -+{
  55.189 -+	return skb_shinfo(skb)->gso_size;
  55.190 -+}
  55.191 -+
  55.192 - #endif	/* __KERNEL__ */
  55.193 - #endif	/* _LINUX_SKBUFF_H */
  55.194 -diff -pruN ../orig-linux-2.6.16.29/include/net/protocol.h ./include/net/protocol.h
  55.195 ---- ../orig-linux-2.6.16.29/include/net/protocol.h	2006-09-19 13:59:20.000000000 +0100
  55.196 -+++ ./include/net/protocol.h	2006-09-19 13:59:46.000000000 +0100
  55.197 -@@ -37,6 +37,7 @@
  55.198 - struct net_protocol {
  55.199 - 	int			(*handler)(struct sk_buff *skb);
  55.200 - 	void			(*err_handler)(struct sk_buff *skb, u32 info);
  55.201 -+	int			(*gso_send_check)(struct sk_buff *skb);
  55.202 - 	struct sk_buff	       *(*gso_segment)(struct sk_buff *skb,
  55.203 - 					       int features);
  55.204 - 	int			no_policy;
  55.205 -diff -pruN ../orig-linux-2.6.16.29/include/net/tcp.h ./include/net/tcp.h
  55.206 ---- ../orig-linux-2.6.16.29/include/net/tcp.h	2006-09-19 13:59:20.000000000 +0100
  55.207 -+++ ./include/net/tcp.h	2006-09-19 13:59:46.000000000 +0100
  55.208 -@@ -1063,6 +1063,7 @@ extern struct request_sock_ops tcp_reque
  55.209 - 
  55.210 - extern int tcp_v4_destroy_sock(struct sock *sk);
  55.211 - 
  55.212 -+extern int tcp_v4_gso_send_check(struct sk_buff *skb);
  55.213 - extern struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features);
  55.214 - 
  55.215 - #ifdef CONFIG_PROC_FS
  55.216 -diff -pruN ../orig-linux-2.6.16.29/net/bridge/br_forward.c ./net/bridge/br_forward.c
  55.217 ---- ../orig-linux-2.6.16.29/net/bridge/br_forward.c	2006-09-19 13:59:20.000000000 +0100
  55.218 -+++ ./net/bridge/br_forward.c	2006-09-19 13:59:46.000000000 +0100
  55.219 -@@ -32,7 +32,7 @@ static inline int should_deliver(const s
  55.220 - int br_dev_queue_push_xmit(struct sk_buff *skb)
  55.221 - {
  55.222 - 	/* drop mtu oversized packets except tso */
  55.223 --	if (skb->len > skb->dev->mtu && !skb_shinfo(skb)->gso_size)
  55.224 -+	if (skb->len > skb->dev->mtu && !skb_is_gso(skb))
  55.225 - 		kfree_skb(skb);
  55.226 - 	else {
  55.227 - #ifdef CONFIG_BRIDGE_NETFILTER
  55.228 -diff -pruN ../orig-linux-2.6.16.29/net/bridge/br_netfilter.c ./net/bridge/br_netfilter.c
  55.229 ---- ../orig-linux-2.6.16.29/net/bridge/br_netfilter.c	2006-09-19 13:59:20.000000000 +0100
  55.230 -+++ ./net/bridge/br_netfilter.c	2006-09-19 13:59:46.000000000 +0100
  55.231 -@@ -743,7 +743,7 @@ static int br_nf_dev_queue_xmit(struct s
  55.232 - {
  55.233 - 	if (skb->protocol == htons(ETH_P_IP) &&
  55.234 - 	    skb->len > skb->dev->mtu &&
  55.235 --	    !skb_shinfo(skb)->gso_size)
  55.236 -+	    !skb_is_gso(skb))
  55.237 - 		return ip_fragment(skb, br_dev_queue_push_xmit);
  55.238 - 	else
  55.239 - 		return br_dev_queue_push_xmit(skb);
  55.240 -diff -pruN ../orig-linux-2.6.16.29/net/core/dev.c ./net/core/dev.c
  55.241 ---- ../orig-linux-2.6.16.29/net/core/dev.c	2006-09-19 13:59:20.000000000 +0100
  55.242 -+++ ./net/core/dev.c	2006-09-19 13:59:46.000000000 +0100
  55.243 -@@ -1083,9 +1083,17 @@ int skb_checksum_help(struct sk_buff *sk
  55.244 - 	unsigned int csum;
  55.245 - 	int ret = 0, offset = skb->h.raw - skb->data;
  55.246 - 
  55.247 --	if (inward) {
  55.248 --		skb->ip_summed = CHECKSUM_NONE;
  55.249 --		goto out;
  55.250 -+	if (inward)
  55.251 -+		goto out_set_summed;
  55.252 -+
  55.253 -+	if (unlikely(skb_shinfo(skb)->gso_size)) {
  55.254 -+		static int warned;
  55.255 -+
  55.256 -+		WARN_ON(!warned);
  55.257 -+		warned = 1;
  55.258 -+
  55.259 -+		/* Let GSO fix up the checksum. */
  55.260 -+		goto out_set_summed;
  55.261 - 	}
  55.262 - 
  55.263 - 	if (skb_cloned(skb)) {
  55.264 -@@ -1102,6 +1110,8 @@ int skb_checksum_help(struct sk_buff *sk
  55.265 - 	BUG_ON(skb->csum + 2 > offset);
  55.266 - 
  55.267 - 	*(u16*)(skb->h.raw + skb->csum) = csum_fold(csum);
  55.268 -+
  55.269 -+out_set_summed:
  55.270 - 	skb->ip_summed = CHECKSUM_NONE;
  55.271 - out:	
  55.272 - 	return ret;
  55.273 -@@ -1122,17 +1132,35 @@ struct sk_buff *skb_gso_segment(struct s
  55.274 - 	struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT);
  55.275 - 	struct packet_type *ptype;
  55.276 - 	int type = skb->protocol;
  55.277 -+	int err;
  55.278 - 
  55.279 - 	BUG_ON(skb_shinfo(skb)->frag_list);
  55.280 --	BUG_ON(skb->ip_summed != CHECKSUM_HW);
  55.281 - 
  55.282 - 	skb->mac.raw = skb->data;
  55.283 - 	skb->mac_len = skb->nh.raw - skb->data;
  55.284 - 	__skb_pull(skb, skb->mac_len);
  55.285 - 
  55.286 -+	if (unlikely(skb->ip_summed != CHECKSUM_HW)) {
  55.287 -+		static int warned;
  55.288 -+
  55.289 -+		WARN_ON(!warned);
  55.290 -+		warned = 1;
  55.291 -+
  55.292 -+		if (skb_header_cloned(skb) &&
  55.293 -+		    (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
  55.294 -+			return ERR_PTR(err);
  55.295 -+	}
  55.296 -+
  55.297 - 	rcu_read_lock();
  55.298 - 	list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type) & 15], list) {
  55.299 - 		if (ptype->type == type && !ptype->dev && ptype->gso_segment) {
  55.300 -+			if (unlikely(skb->ip_summed != CHECKSUM_HW)) {
  55.301 -+				err = ptype->gso_send_check(skb);
  55.302 -+				segs = ERR_PTR(err);
  55.303 -+				if (err || skb_gso_ok(skb, features))
  55.304 -+					break;
  55.305 -+				__skb_push(skb, skb->data - skb->nh.raw);
  55.306 -+			}
  55.307 - 			segs = ptype->gso_segment(skb, features);
  55.308 - 			break;
  55.309 - 		}
  55.310 -diff -pruN ../orig-linux-2.6.16.29/net/ipv4/af_inet.c ./net/ipv4/af_inet.c
  55.311 ---- ../orig-linux-2.6.16.29/net/ipv4/af_inet.c	2006-09-19 13:59:20.000000000 +0100
  55.312 -+++ ./net/ipv4/af_inet.c	2006-09-19 13:59:46.000000000 +0100
  55.313 -@@ -1085,6 +1085,40 @@ int inet_sk_rebuild_header(struct sock *
  55.314 - 
  55.315 - EXPORT_SYMBOL(inet_sk_rebuild_header);
  55.316 - 
  55.317 -+static int inet_gso_send_check(struct sk_buff *skb)
  55.318 -+{
  55.319 -+	struct iphdr *iph;
  55.320 -+	struct net_protocol *ops;
  55.321 -+	int proto;
  55.322 -+	int ihl;
  55.323 -+	int err = -EINVAL;
  55.324 -+
  55.325 -+	if (unlikely(!pskb_may_pull(skb, sizeof(*iph))))
  55.326 -+		goto out;
  55.327 -+
  55.328 -+	iph = skb->nh.iph;
  55.329 -+	ihl = iph->ihl * 4;
  55.330 -+	if (ihl < sizeof(*iph))
  55.331 -+		goto out;
  55.332 -+
  55.333 -+	if (unlikely(!pskb_may_pull(skb, ihl)))
  55.334 -+		goto out;
  55.335 -+
  55.336 -+	skb->h.raw = __skb_pull(skb, ihl);
  55.337 -+	iph = skb->nh.iph;
  55.338 -+	proto = iph->protocol & (MAX_INET_PROTOS - 1);
  55.339 -+	err = -EPROTONOSUPPORT;
  55.340 -+
  55.341 -+	rcu_read_lock();
  55.342 -+	ops = rcu_dereference(inet_protos[proto]);
  55.343 -+	if (likely(ops && ops->gso_send_check))
  55.344 -+		err = ops->gso_send_check(skb);
  55.345 -+	rcu_read_unlock();
  55.346 -+
  55.347 -+out:
  55.348 -+	return err;
  55.349 -+}
  55.350 -+
  55.351 - static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int features)
  55.352 - {
  55.353 - 	struct sk_buff *segs = ERR_PTR(-EINVAL);
  55.354 -@@ -1142,6 +1176,7 @@ static struct net_protocol igmp_protocol
  55.355 - static struct net_protocol tcp_protocol = {
  55.356 - 	.handler =	tcp_v4_rcv,
  55.357 - 	.err_handler =	tcp_v4_err,
  55.358 -+	.gso_send_check = tcp_v4_gso_send_check,
  55.359 - 	.gso_segment =	tcp_tso_segment,
  55.360 - 	.no_policy =	1,
  55.361 - };
  55.362 -@@ -1188,6 +1223,7 @@ static int ipv4_proc_init(void);
  55.363 - static struct packet_type ip_packet_type = {
  55.364 - 	.type = __constant_htons(ETH_P_IP),
  55.365 - 	.func = ip_rcv,
  55.366 -+	.gso_send_check = inet_gso_send_check,
  55.367 - 	.gso_segment = inet_gso_segment,
  55.368 - };
  55.369 - 
  55.370 -diff -pruN ../orig-linux-2.6.16.29/net/ipv4/ip_output.c ./net/ipv4/ip_output.c
  55.371 ---- ../orig-linux-2.6.16.29/net/ipv4/ip_output.c	2006-09-19 13:59:20.000000000 +0100
  55.372 -+++ ./net/ipv4/ip_output.c	2006-09-19 13:59:46.000000000 +0100
  55.373 -@@ -210,7 +210,7 @@ static inline int ip_finish_output(struc
  55.374 - 		return dst_output(skb);
  55.375 - 	}
  55.376 - #endif
  55.377 --	if (skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->gso_size)
  55.378 -+	if (skb->len > dst_mtu(skb->dst) && !skb_is_gso(skb))
  55.379 - 		return ip_fragment(skb, ip_finish_output2);
  55.380 - 	else
  55.381 - 		return ip_finish_output2(skb);
  55.382 -@@ -1095,7 +1095,7 @@ ssize_t	ip_append_page(struct sock *sk, 
  55.383 - 	while (size > 0) {
  55.384 - 		int i;
  55.385 - 
  55.386 --		if (skb_shinfo(skb)->gso_size)
  55.387 -+		if (skb_is_gso(skb))
  55.388 - 			len = size;
  55.389 - 		else {
  55.390 - 
  55.391 -diff -pruN ../orig-linux-2.6.16.29/net/ipv4/tcp_ipv4.c ./net/ipv4/tcp_ipv4.c
  55.392 ---- ../orig-linux-2.6.16.29/net/ipv4/tcp_ipv4.c	2006-09-12 19:02:10.000000000 +0100
  55.393 -+++ ./net/ipv4/tcp_ipv4.c	2006-09-19 13:59:46.000000000 +0100
  55.394 -@@ -495,6 +495,24 @@ void tcp_v4_send_check(struct sock *sk, 
  55.395 - 	}
  55.396 - }
  55.397 - 
  55.398 -+int tcp_v4_gso_send_check(struct sk_buff *skb)
  55.399 -+{
  55.400 -+	struct iphdr *iph;
  55.401 -+	struct tcphdr *th;
  55.402 -+
  55.403 -+	if (!pskb_may_pull(skb, sizeof(*th)))
  55.404 -+		return -EINVAL;
  55.405 -+
  55.406 -+	iph = skb->nh.iph;
  55.407 -+	th = skb->h.th;
  55.408 -+
  55.409 -+	th->check = 0;
  55.410 -+	th->check = ~tcp_v4_check(th, skb->len, iph->saddr, iph->daddr, 0);
  55.411 -+	skb->csum = offsetof(struct tcphdr, check);
  55.412 -+	skb->ip_summed = CHECKSUM_HW;
  55.413 -+	return 0;
  55.414 -+}
  55.415 -+
  55.416 - /*
  55.417 -  *	This routine will send an RST to the other tcp.
  55.418 -  *
  55.419 -diff -pruN ../orig-linux-2.6.16.29/net/ipv4/xfrm4_output.c ./net/ipv4/xfrm4_output.c
  55.420 ---- ../orig-linux-2.6.16.29/net/ipv4/xfrm4_output.c	2006-09-19 13:59:20.000000000 +0100
  55.421 -+++ ./net/ipv4/xfrm4_output.c	2006-09-19 13:59:46.000000000 +0100
  55.422 -@@ -195,7 +195,7 @@ static int xfrm4_output_finish(struct sk
  55.423 - 	}
  55.424 - #endif
  55.425 - 
  55.426 --	if (!skb_shinfo(skb)->gso_size)
  55.427 -+	if (!skb_is_gso(skb))
  55.428 - 		return xfrm4_output_finish2(skb);
  55.429 - 
  55.430 - 	skb->protocol = htons(ETH_P_IP);
  55.431 -diff -pruN ../orig-linux-2.6.16.29/net/ipv6/ip6_output.c ./net/ipv6/ip6_output.c
  55.432 ---- ../orig-linux-2.6.16.29/net/ipv6/ip6_output.c	2006-09-19 13:59:20.000000000 +0100
  55.433 -+++ ./net/ipv6/ip6_output.c	2006-09-19 13:59:46.000000000 +0100
  55.434 -@@ -147,7 +147,7 @@ static int ip6_output2(struct sk_buff *s
  55.435 - 
  55.436 - int ip6_output(struct sk_buff *skb)
  55.437 - {
  55.438 --	if ((skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->gso_size) ||
  55.439 -+	if ((skb->len > dst_mtu(skb->dst) && !skb_is_gso(skb)) ||
  55.440 - 				dst_allfrag(skb->dst))
  55.441 - 		return ip6_fragment(skb, ip6_output2);
  55.442 - 	else
  55.443 -diff -pruN ../orig-linux-2.6.16.29/net/ipv6/xfrm6_output.c ./net/ipv6/xfrm6_output.c
  55.444 ---- ../orig-linux-2.6.16.29/net/ipv6/xfrm6_output.c	2006-09-19 13:59:20.000000000 +0100
  55.445 -+++ ./net/ipv6/xfrm6_output.c	2006-09-19 13:59:46.000000000 +0100
  55.446 -@@ -179,7 +179,7 @@ static int xfrm6_output_finish(struct sk
  55.447 - {
  55.448 - 	struct sk_buff *segs;
  55.449 - 
  55.450 --	if (!skb_shinfo(skb)->gso_size)
  55.451 -+	if (!skb_is_gso(skb))
  55.452 - 		return xfrm6_output_finish2(skb);
  55.453 - 
  55.454 - 	skb->protocol = htons(ETH_P_IP);
    56.1 --- a/patches/linux-2.6.16.29/net-gso-3-fix-errorcheck.patch	Mon Nov 27 10:10:57 2006 -0700
    56.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    56.3 @@ -1,17 +0,0 @@
    56.4 -diff -pruN ../orig-linux-2.6.16.29/include/linux/netdevice.h ./include/linux/netdevice.h
    56.5 ---- ../orig-linux-2.6.16.29/include/linux/netdevice.h	2006-09-19 13:59:46.000000000 +0100
    56.6 -+++ ./include/linux/netdevice.h	2006-09-19 14:05:28.000000000 +0100
    56.7 -@@ -930,10 +930,10 @@ static inline void netif_tx_lock_bh(stru
    56.8 - 
    56.9 - static inline int netif_tx_trylock(struct net_device *dev)
   56.10 - {
   56.11 --	int err = spin_trylock(&dev->_xmit_lock);
   56.12 --	if (!err)
   56.13 -+	int ok = spin_trylock(&dev->_xmit_lock);
   56.14 -+	if (likely(ok))
   56.15 - 		dev->xmit_lock_owner = smp_processor_id();
   56.16 --	return err;
   56.17 -+	return ok;
   56.18 - }
   56.19 - 
   56.20 - static inline void netif_tx_unlock(struct net_device *dev)
    57.1 --- a/patches/linux-2.6.16.29/net-gso-4-kill-warnon.patch	Mon Nov 27 10:10:57 2006 -0700
    57.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    57.3 @@ -1,27 +0,0 @@
    57.4 -diff -pruN ../orig-linux-2.6.16.29/net/core/dev.c ./net/core/dev.c
    57.5 ---- ../orig-linux-2.6.16.29/net/core/dev.c	2006-09-19 13:59:46.000000000 +0100
    57.6 -+++ ./net/core/dev.c	2006-09-19 14:05:32.000000000 +0100
    57.7 -@@ -1087,11 +1087,6 @@ int skb_checksum_help(struct sk_buff *sk
    57.8 - 		goto out_set_summed;
    57.9 - 
   57.10 - 	if (unlikely(skb_shinfo(skb)->gso_size)) {
   57.11 --		static int warned;
   57.12 --
   57.13 --		WARN_ON(!warned);
   57.14 --		warned = 1;
   57.15 --
   57.16 - 		/* Let GSO fix up the checksum. */
   57.17 - 		goto out_set_summed;
   57.18 - 	}
   57.19 -@@ -1141,11 +1136,6 @@ struct sk_buff *skb_gso_segment(struct s
   57.20 - 	__skb_pull(skb, skb->mac_len);
   57.21 - 
   57.22 - 	if (unlikely(skb->ip_summed != CHECKSUM_HW)) {
   57.23 --		static int warned;
   57.24 --
   57.25 --		WARN_ON(!warned);
   57.26 --		warned = 1;
   57.27 --
   57.28 - 		if (skb_header_cloned(skb) &&
   57.29 - 		    (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
   57.30 - 			return ERR_PTR(err);
    58.1 --- a/patches/linux-2.6.16.29/net-gso-5-rcv-mss.patch	Mon Nov 27 10:10:57 2006 -0700
    58.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    58.3 @@ -1,13 +0,0 @@
    58.4 -diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
    58.5 -index 104af5d..1fa1536 100644
    58.6 ---- a/net/ipv4/tcp_input.c
    58.7 -+++ b/net/ipv4/tcp_input.c
    58.8 -@@ -127,7 +127,7 @@ static void tcp_measure_rcv_mss(struct s
    58.9 - 	/* skb->len may jitter because of SACKs, even if peer
   58.10 - 	 * sends good full-sized frames.
   58.11 - 	 */
   58.12 --	len = skb->len;
   58.13 -+	len = skb_shinfo(skb)->gso_size ?: skb->len;
   58.14 - 	if (len >= icsk->icsk_ack.rcv_mss) {
   58.15 - 		icsk->icsk_ack.rcv_mss = len;
   58.16 - 	} else {
    59.1 --- a/patches/linux-2.6.16.29/pci-mmconfig-fix-from-2.6.17.patch	Mon Nov 27 10:10:57 2006 -0700
    59.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    59.3 @@ -1,292 +0,0 @@
    59.4 -diff -pruN ../orig-linux-2.6.16.29/arch/i386/pci/mmconfig.c ./arch/i386/pci/mmconfig.c
    59.5 ---- ../orig-linux-2.6.16.29/arch/i386/pci/mmconfig.c	2006-09-12 19:02:10.000000000 +0100
    59.6 -+++ ./arch/i386/pci/mmconfig.c	2006-09-21 09:35:27.000000000 +0100
    59.7 -@@ -12,14 +12,22 @@
    59.8 - #include <linux/pci.h>
    59.9 - #include <linux/init.h>
   59.10 - #include <linux/acpi.h>
   59.11 -+#include <asm/e820.h>
   59.12 - #include "pci.h"
   59.13 - 
   59.14 -+/* aperture is up to 256MB but BIOS may reserve less */
   59.15 -+#define MMCONFIG_APER_MIN	(2 * 1024*1024)
   59.16 -+#define MMCONFIG_APER_MAX	(256 * 1024*1024)
   59.17 -+
   59.18 -+/* Assume systems with more busses have correct MCFG */
   59.19 -+#define MAX_CHECK_BUS 16
   59.20 -+
   59.21 - #define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG))
   59.22 - 
   59.23 - /* The base address of the last MMCONFIG device accessed */
   59.24 - static u32 mmcfg_last_accessed_device;
   59.25 - 
   59.26 --static DECLARE_BITMAP(fallback_slots, 32);
   59.27 -+static DECLARE_BITMAP(fallback_slots, MAX_CHECK_BUS*32);
   59.28 - 
   59.29 - /*
   59.30 -  * Functions for accessing PCI configuration space with MMCONFIG accesses
   59.31 -@@ -29,8 +37,8 @@ static u32 get_base_addr(unsigned int se
   59.32 - 	int cfg_num = -1;
   59.33 - 	struct acpi_table_mcfg_config *cfg;
   59.34 - 
   59.35 --	if (seg == 0 && bus == 0 &&
   59.36 --	    test_bit(PCI_SLOT(devfn), fallback_slots))
   59.37 -+	if (seg == 0 && bus < MAX_CHECK_BUS &&
   59.38 -+	    test_bit(PCI_SLOT(devfn) + 32*bus, fallback_slots))
   59.39 - 		return 0;
   59.40 - 
   59.41 - 	while (1) {
   59.42 -@@ -74,8 +82,10 @@ static int pci_mmcfg_read(unsigned int s
   59.43 - 	unsigned long flags;
   59.44 - 	u32 base;
   59.45 - 
   59.46 --	if (!value || (bus > 255) || (devfn > 255) || (reg > 4095))
   59.47 -+	if ((bus > 255) || (devfn > 255) || (reg > 4095)) {
   59.48 -+		*value = -1;
   59.49 - 		return -EINVAL;
   59.50 -+	}
   59.51 - 
   59.52 - 	base = get_base_addr(seg, bus, devfn);
   59.53 - 	if (!base)
   59.54 -@@ -146,30 +156,66 @@ static struct pci_raw_ops pci_mmcfg = {
   59.55 -    Normally this can be expressed in the MCFG by not listing them
   59.56 -    and assigning suitable _SEGs, but this isn't implemented in some BIOS.
   59.57 -    Instead try to discover all devices on bus 0 that are unreachable using MM
   59.58 --   and fallback for them.
   59.59 --   We only do this for bus 0/seg 0 */
   59.60 -+   and fallback for them. */
   59.61 - static __init void unreachable_devices(void)
   59.62 - {
   59.63 --	int i;
   59.64 -+	int i, k;
   59.65 - 	unsigned long flags;
   59.66 - 
   59.67 --	for (i = 0; i < 32; i++) {
   59.68 --		u32 val1;
   59.69 --		u32 addr;
   59.70 -+	for (k = 0; k < MAX_CHECK_BUS; k++) {
   59.71 -+		for (i = 0; i < 32; i++) {
   59.72 -+			u32 val1;
   59.73 -+			u32 addr;
   59.74 -+
   59.75 -+			pci_conf1_read(0, k, PCI_DEVFN(i, 0), 0, 4, &val1);
   59.76 -+			if (val1 == 0xffffffff)
   59.77 -+				continue;
   59.78 -+
   59.79 -+			/* Locking probably not needed, but safer */
   59.80 -+			spin_lock_irqsave(&pci_config_lock, flags);
   59.81 -+			addr = get_base_addr(0, k, PCI_DEVFN(i, 0));
   59.82 -+			if (addr != 0)
   59.83 -+				pci_exp_set_dev_base(addr, k, PCI_DEVFN(i, 0));
   59.84 -+			if (addr == 0 ||
   59.85 -+			    readl((u32 __iomem *)mmcfg_virt_addr) != val1) {
   59.86 -+				set_bit(i, fallback_slots);
   59.87 -+				printk(KERN_NOTICE
   59.88 -+			"PCI: No mmconfig possible on %x:%x\n", k, i);
   59.89 -+			}
   59.90 -+			spin_unlock_irqrestore(&pci_config_lock, flags);
   59.91 -+		}
   59.92 -+	}
   59.93 -+}
   59.94 - 
   59.95 --		pci_conf1_read(0, 0, PCI_DEVFN(i, 0), 0, 4, &val1);
   59.96 --		if (val1 == 0xffffffff)
   59.97 -+/* NB. Ripped from arch/i386/kernel/setup.c for this Xen bugfix patch. */
   59.98 -+#ifdef CONFIG_XEN
   59.99 -+extern struct e820map machine_e820;
  59.100 -+#define e820 machine_e820
  59.101 -+#endif
  59.102 -+static int __init
  59.103 -+e820_all_mapped(unsigned long s, unsigned long e, unsigned type)
  59.104 -+{
  59.105 -+	u64 start = s;
  59.106 -+	u64 end = e;
  59.107 -+	int i;
  59.108 -+	for (i = 0; i < e820.nr_map; i++) {
  59.109 -+		struct e820entry *ei = &e820.map[i];
  59.110 -+		if (type && ei->type != type)
  59.111 - 			continue;
  59.112 --
  59.113 --		/* Locking probably not needed, but safer */
  59.114 --		spin_lock_irqsave(&pci_config_lock, flags);
  59.115 --		addr = get_base_addr(0, 0, PCI_DEVFN(i, 0));
  59.116 --		if (addr != 0)
  59.117 --			pci_exp_set_dev_base(addr, 0, PCI_DEVFN(i, 0));
  59.118 --		if (addr == 0 || readl((u32 __iomem *)mmcfg_virt_addr) != val1)
  59.119 --			set_bit(i, fallback_slots);
  59.120 --		spin_unlock_irqrestore(&pci_config_lock, flags);
  59.121 -+		/* is the region (part) in overlap with the current region ?*/
  59.122 -+		if (ei->addr >= end || ei->addr + ei->size <= start)
  59.123 -+			continue;
  59.124 -+		/* if the region is at the beginning of <start,end> we move
  59.125 -+		 * start to the end of the region since it's ok until there
  59.126 -+		 */
  59.127 -+		if (ei->addr <= start)
  59.128 -+			start = ei->addr + ei->size;
  59.129 -+		/* if start is now at or beyond end, we're done, full
  59.130 -+		 * coverage */
  59.131 -+		if (start >= end)
  59.132 -+			return 1; /* we're done */
  59.133 - 	}
  59.134 -+	return 0;
  59.135 - }
  59.136 - 
  59.137 - static int __init pci_mmcfg_init(void)
  59.138 -@@ -183,6 +229,15 @@ static int __init pci_mmcfg_init(void)
  59.139 - 	    (pci_mmcfg_config[0].base_address == 0))
  59.140 - 		goto out;
  59.141 - 
  59.142 -+	if (!e820_all_mapped(pci_mmcfg_config[0].base_address,
  59.143 -+			pci_mmcfg_config[0].base_address + MMCONFIG_APER_MIN,
  59.144 -+			E820_RESERVED)) {
  59.145 -+		printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %x is not E820-reserved\n",
  59.146 -+				pci_mmcfg_config[0].base_address);
  59.147 -+		printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
  59.148 -+		goto out;
  59.149 -+	}
  59.150 -+
  59.151 - 	printk(KERN_INFO "PCI: Using MMCONFIG\n");
  59.152 - 	raw_pci_ops = &pci_mmcfg;
  59.153 - 	pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
  59.154 -diff -pruN ../orig-linux-2.6.16.29/arch/x86_64/pci/mmconfig.c ./arch/x86_64/pci/mmconfig.c
  59.155 ---- ../orig-linux-2.6.16.29/arch/x86_64/pci/mmconfig.c	2006-09-12 19:02:10.000000000 +0100
  59.156 -+++ ./arch/x86_64/pci/mmconfig.c	2006-09-21 09:35:40.000000000 +0100
  59.157 -@@ -9,11 +9,19 @@
  59.158 - #include <linux/init.h>
  59.159 - #include <linux/acpi.h>
  59.160 - #include <linux/bitmap.h>
  59.161 -+#include <asm/e820.h>
  59.162 -+
  59.163 - #include "pci.h"
  59.164 - 
  59.165 --#define MMCONFIG_APER_SIZE (256*1024*1024)
  59.166 -+/* aperture is up to 256MB but BIOS may reserve less */
  59.167 -+#define MMCONFIG_APER_MIN	(2 * 1024*1024)
  59.168 -+#define MMCONFIG_APER_MAX	(256 * 1024*1024)
  59.169 -+
  59.170 -+/* Verify the first 16 busses. We assume that systems with more busses
  59.171 -+   get MCFG right. */
  59.172 -+#define MAX_CHECK_BUS 16
  59.173 - 
  59.174 --static DECLARE_BITMAP(fallback_slots, 32);
  59.175 -+static DECLARE_BITMAP(fallback_slots, 32*MAX_CHECK_BUS);
  59.176 - 
  59.177 - /* Static virtual mapping of the MMCONFIG aperture */
  59.178 - struct mmcfg_virt {
  59.179 -@@ -55,7 +63,8 @@ static char __iomem *get_virt(unsigned i
  59.180 - static char __iomem *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn)
  59.181 - {
  59.182 - 	char __iomem *addr;
  59.183 --	if (seg == 0 && bus == 0 && test_bit(PCI_SLOT(devfn), &fallback_slots))
  59.184 -+	if (seg == 0 && bus < MAX_CHECK_BUS &&
  59.185 -+		test_bit(32*bus + PCI_SLOT(devfn), fallback_slots))
  59.186 - 		return NULL;
  59.187 - 	addr = get_virt(seg, bus);
  59.188 - 	if (!addr)
  59.189 -@@ -69,8 +78,10 @@ static int pci_mmcfg_read(unsigned int s
  59.190 - 	char __iomem *addr;
  59.191 - 
  59.192 - 	/* Why do we have this when nobody checks it. How about a BUG()!? -AK */
  59.193 --	if (unlikely(!value || (bus > 255) || (devfn > 255) || (reg > 4095)))
  59.194 -+	if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095))) {
  59.195 -+		*value = -1;
  59.196 - 		return -EINVAL;
  59.197 -+	}
  59.198 - 
  59.199 - 	addr = pci_dev_base(seg, bus, devfn);
  59.200 - 	if (!addr)
  59.201 -@@ -129,23 +140,56 @@ static struct pci_raw_ops pci_mmcfg = {
  59.202 -    Normally this can be expressed in the MCFG by not listing them
  59.203 -    and assigning suitable _SEGs, but this isn't implemented in some BIOS.
  59.204 -    Instead try to discover all devices on bus 0 that are unreachable using MM
  59.205 --   and fallback for them.
  59.206 --   We only do this for bus 0/seg 0 */
  59.207 -+   and fallback for them. */
  59.208 - static __init void unreachable_devices(void)
  59.209 - {
  59.210 --	int i;
  59.211 --	for (i = 0; i < 32; i++) {
  59.212 --		u32 val1;
  59.213 --		char __iomem *addr;
  59.214 -+	int i, k;
  59.215 -+	/* Use the max bus number from ACPI here? */
  59.216 -+	for (k = 0; k < MAX_CHECK_BUS; k++) {
  59.217 -+		for (i = 0; i < 32; i++) {
  59.218 -+			u32 val1;
  59.219 -+			char __iomem *addr;
  59.220 -+
  59.221 -+			pci_conf1_read(0, k, PCI_DEVFN(i,0), 0, 4, &val1);
  59.222 -+			if (val1 == 0xffffffff)
  59.223 -+				continue;
  59.224 -+			addr = pci_dev_base(0, k, PCI_DEVFN(i, 0));
  59.225 -+			if (addr == NULL|| readl(addr) != val1) {
  59.226 -+				set_bit(i + 32*k, fallback_slots);
  59.227 -+				printk(KERN_NOTICE
  59.228 -+				"PCI: No mmconfig possible on device %x:%x\n",
  59.229 -+					k, i);
  59.230 -+			}
  59.231 -+		}
  59.232 -+	}
  59.233 -+}
  59.234 - 
  59.235 --		pci_conf1_read(0, 0, PCI_DEVFN(i,0), 0, 4, &val1);
  59.236 --		if (val1 == 0xffffffff)
  59.237 -+/* NB. Ripped from arch/x86_64/kernel/e820.c for this Xen bugfix patch. */
  59.238 -+#ifdef CONFIG_XEN
  59.239 -+extern struct e820map machine_e820;
  59.240 -+#define e820 machine_e820
  59.241 -+#endif
  59.242 -+static int __init e820_all_mapped(unsigned long start, unsigned long end, unsigned type)
  59.243 -+{
  59.244 -+	int i;
  59.245 -+	for (i = 0; i < e820.nr_map; i++) {
  59.246 -+		struct e820entry *ei = &e820.map[i];
  59.247 -+		if (type && ei->type != type)
  59.248 - 			continue;
  59.249 --		addr = pci_dev_base(0, 0, PCI_DEVFN(i, 0));
  59.250 --		if (addr == NULL|| readl(addr) != val1) {
  59.251 --			set_bit(i, &fallback_slots);
  59.252 --		}
  59.253 -+		/* is the region (part) in overlap with the current region ?*/
  59.254 -+		if (ei->addr >= end || ei->addr + ei->size <= start)
  59.255 -+			continue;
  59.256 -+
  59.257 -+		/* if the region is at the beginning of <start,end> we move
  59.258 -+		 * start to the end of the region since it's ok until there
  59.259 -+		 */
  59.260 -+		if (ei->addr <= start)
  59.261 -+			start = ei->addr + ei->size;
  59.262 -+		/* if start is now at or beyond end, we're done, full coverage */
  59.263 -+		if (start >= end)
  59.264 -+			return 1; /* we're done */
  59.265 - 	}
  59.266 -+	return 0;
  59.267 - }
  59.268 - 
  59.269 - static int __init pci_mmcfg_init(void)
  59.270 -@@ -161,6 +205,15 @@ static int __init pci_mmcfg_init(void)
  59.271 - 	    (pci_mmcfg_config[0].base_address == 0))
  59.272 - 		return 0;
  59.273 - 
  59.274 -+	if (!e820_all_mapped(pci_mmcfg_config[0].base_address,
  59.275 -+			pci_mmcfg_config[0].base_address + MMCONFIG_APER_MIN,
  59.276 -+			E820_RESERVED)) {
  59.277 -+		printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %x is not E820-reserved\n",
  59.278 -+				pci_mmcfg_config[0].base_address);
  59.279 -+		printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
  59.280 -+		return 0;
  59.281 -+	}
  59.282 -+
  59.283 - 	/* RED-PEN i386 doesn't do _nocache right now */
  59.284 - 	pci_mmcfg_virt = kmalloc(sizeof(*pci_mmcfg_virt) * pci_mmcfg_config_num, GFP_KERNEL);
  59.285 - 	if (pci_mmcfg_virt == NULL) {
  59.286 -@@ -169,7 +222,8 @@ static int __init pci_mmcfg_init(void)
  59.287 - 	}
  59.288 - 	for (i = 0; i < pci_mmcfg_config_num; ++i) {
  59.289 - 		pci_mmcfg_virt[i].cfg = &pci_mmcfg_config[i];
  59.290 --		pci_mmcfg_virt[i].virt = ioremap_nocache(pci_mmcfg_config[i].base_address, MMCONFIG_APER_SIZE);
  59.291 -+		pci_mmcfg_virt[i].virt = ioremap_nocache(pci_mmcfg_config[i].base_address,
  59.292 -+							 MMCONFIG_APER_MAX);
  59.293 - 		if (!pci_mmcfg_virt[i].virt) {
  59.294 - 			printk("PCI: Cannot map mmconfig aperture for segment %d\n",
  59.295 - 			       pci_mmcfg_config[i].pci_segment_group_number);
    60.1 --- a/patches/linux-2.6.16.29/pmd-shared.patch	Mon Nov 27 10:10:57 2006 -0700
    60.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    60.3 @@ -1,111 +0,0 @@
    60.4 -diff -pruN ../orig-linux-2.6.16.29/arch/i386/mm/pageattr.c ./arch/i386/mm/pageattr.c
    60.5 ---- ../orig-linux-2.6.16.29/arch/i386/mm/pageattr.c	2006-09-12 19:02:10.000000000 +0100
    60.6 -+++ ./arch/i386/mm/pageattr.c	2006-09-19 14:05:35.000000000 +0100
    60.7 -@@ -78,7 +78,7 @@ static void set_pmd_pte(pte_t *kpte, uns
    60.8 - 	unsigned long flags;
    60.9 - 
   60.10 - 	set_pte_atomic(kpte, pte); 	/* change init_mm */
   60.11 --	if (PTRS_PER_PMD > 1)
   60.12 -+	if (HAVE_SHARED_KERNEL_PMD)
   60.13 - 		return;
   60.14 - 
   60.15 - 	spin_lock_irqsave(&pgd_lock, flags);
   60.16 -diff -pruN ../orig-linux-2.6.16.29/arch/i386/mm/pgtable.c ./arch/i386/mm/pgtable.c
   60.17 ---- ../orig-linux-2.6.16.29/arch/i386/mm/pgtable.c	2006-09-12 19:02:10.000000000 +0100
   60.18 -+++ ./arch/i386/mm/pgtable.c	2006-09-19 14:05:35.000000000 +0100
   60.19 -@@ -215,9 +215,10 @@ void pgd_ctor(void *pgd, kmem_cache_t *c
   60.20 - 		spin_lock_irqsave(&pgd_lock, flags);
   60.21 - 	}
   60.22 - 
   60.23 --	clone_pgd_range((pgd_t *)pgd + USER_PTRS_PER_PGD,
   60.24 --			swapper_pg_dir + USER_PTRS_PER_PGD,
   60.25 --			KERNEL_PGD_PTRS);
   60.26 -+	if (PTRS_PER_PMD == 1 || HAVE_SHARED_KERNEL_PMD)
   60.27 -+		clone_pgd_range((pgd_t *)pgd + USER_PTRS_PER_PGD,
   60.28 -+				swapper_pg_dir + USER_PTRS_PER_PGD,
   60.29 -+				KERNEL_PGD_PTRS);
   60.30 - 	if (PTRS_PER_PMD > 1)
   60.31 - 		return;
   60.32 - 
   60.33 -@@ -249,6 +250,30 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
   60.34 - 			goto out_oom;
   60.35 - 		set_pgd(&pgd[i], __pgd(1 + __pa(pmd)));
   60.36 - 	}
   60.37 -+
   60.38 -+	if (!HAVE_SHARED_KERNEL_PMD) {
   60.39 -+		unsigned long flags;
   60.40 -+
   60.41 -+		for (i = USER_PTRS_PER_PGD; i < PTRS_PER_PGD; i++) {
   60.42 -+			pmd_t *pmd = kmem_cache_alloc(pmd_cache, GFP_KERNEL);
   60.43 -+			if (!pmd)
   60.44 -+				goto out_oom;
   60.45 -+			set_pgd(&pgd[USER_PTRS_PER_PGD], __pgd(1 + __pa(pmd)));
   60.46 -+		}
   60.47 -+
   60.48 -+		spin_lock_irqsave(&pgd_lock, flags);
   60.49 -+		for (i = USER_PTRS_PER_PGD; i < PTRS_PER_PGD; i++) {
   60.50 -+			unsigned long v = (unsigned long)i << PGDIR_SHIFT;
   60.51 -+			pgd_t *kpgd = pgd_offset_k(v);
   60.52 -+			pud_t *kpud = pud_offset(kpgd, v);
   60.53 -+			pmd_t *kpmd = pmd_offset(kpud, v);
   60.54 -+			pmd_t *pmd = (void *)__va(pgd_val(pgd[i])-1);
   60.55 -+			memcpy(pmd, kpmd, PAGE_SIZE);
   60.56 -+		}
   60.57 -+		pgd_list_add(pgd);
   60.58 -+		spin_unlock_irqrestore(&pgd_lock, flags);
   60.59 -+	}
   60.60 -+
   60.61 - 	return pgd;
   60.62 - 
   60.63 - out_oom:
   60.64 -@@ -263,9 +288,23 @@ void pgd_free(pgd_t *pgd)
   60.65 - 	int i;
   60.66 - 
   60.67 - 	/* in the PAE case user pgd entries are overwritten before usage */
   60.68 --	if (PTRS_PER_PMD > 1)
   60.69 --		for (i = 0; i < USER_PTRS_PER_PGD; ++i)
   60.70 --			kmem_cache_free(pmd_cache, (void *)__va(pgd_val(pgd[i])-1));
   60.71 -+	if (PTRS_PER_PMD > 1) {
   60.72 -+		for (i = 0; i < USER_PTRS_PER_PGD; ++i) {
   60.73 -+			pmd_t *pmd = (void *)__va(pgd_val(pgd[i])-1);
   60.74 -+			kmem_cache_free(pmd_cache, pmd);
   60.75 -+		}
   60.76 -+		if (!HAVE_SHARED_KERNEL_PMD) {
   60.77 -+			unsigned long flags;
   60.78 -+			spin_lock_irqsave(&pgd_lock, flags);
   60.79 -+			pgd_list_del(pgd);
   60.80 -+			spin_unlock_irqrestore(&pgd_lock, flags);
   60.81 -+			for (i = USER_PTRS_PER_PGD; i < PTRS_PER_PGD; i++) {
   60.82 -+				pmd_t *pmd = (void *)__va(pgd_val(pgd[i])-1);
   60.83 -+				memset(pmd, 0, PTRS_PER_PMD*sizeof(pmd_t));
   60.84 -+				kmem_cache_free(pmd_cache, pmd);
   60.85 -+			}
   60.86 -+		}
   60.87 -+	}
   60.88 - 	/* in the non-PAE case, free_pgtables() clears user pgd entries */
   60.89 - 	kmem_cache_free(pgd_cache, pgd);
   60.90 - }
   60.91 -diff -pruN ../orig-linux-2.6.16.29/include/asm-i386/pgtable-2level-defs.h ./include/asm-i386/pgtable-2level-defs.h
   60.92 ---- ../orig-linux-2.6.16.29/include/asm-i386/pgtable-2level-defs.h	2006-09-12 19:02:10.000000000 +0100
   60.93 -+++ ./include/asm-i386/pgtable-2level-defs.h	2006-09-19 14:05:35.000000000 +0100
   60.94 -@@ -1,6 +1,8 @@
   60.95 - #ifndef _I386_PGTABLE_2LEVEL_DEFS_H
   60.96 - #define _I386_PGTABLE_2LEVEL_DEFS_H
   60.97 - 
   60.98 -+#define HAVE_SHARED_KERNEL_PMD 0
   60.99 -+
  60.100 - /*
  60.101 -  * traditional i386 two-level paging structure:
  60.102 -  */
  60.103 -diff -pruN ../orig-linux-2.6.16.29/include/asm-i386/pgtable-3level-defs.h ./include/asm-i386/pgtable-3level-defs.h
  60.104 ---- ../orig-linux-2.6.16.29/include/asm-i386/pgtable-3level-defs.h	2006-09-12 19:02:10.000000000 +0100
  60.105 -+++ ./include/asm-i386/pgtable-3level-defs.h	2006-09-19 14:05:35.000000000 +0100
  60.106 -@@ -1,6 +1,8 @@
  60.107 - #ifndef _I386_PGTABLE_3LEVEL_DEFS_H
  60.108 - #define _I386_PGTABLE_3LEVEL_DEFS_H
  60.109 - 
  60.110 -+#define HAVE_SHARED_KERNEL_PMD 1
  60.111 -+
  60.112 - /*
  60.113 -  * PGDIR_SHIFT determines what a top-level page table entry can map
  60.114 -  */
    61.1 --- a/patches/linux-2.6.16.29/rcu_needs_cpu.patch	Mon Nov 27 10:10:57 2006 -0700
    61.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    61.3 @@ -1,35 +0,0 @@
    61.4 -diff -pruN ../orig-linux-2.6.16.29/include/linux/rcupdate.h ./include/linux/rcupdate.h
    61.5 ---- ../orig-linux-2.6.16.29/include/linux/rcupdate.h	2006-09-12 19:02:10.000000000 +0100
    61.6 -+++ ./include/linux/rcupdate.h	2006-09-19 14:05:39.000000000 +0100
    61.7 -@@ -134,6 +134,7 @@ static inline void rcu_bh_qsctr_inc(int 
    61.8 - }
    61.9 - 
   61.10 - extern int rcu_pending(int cpu);
   61.11 -+extern int rcu_needs_cpu(int cpu);
   61.12 - 
   61.13 - /**
   61.14 -  * rcu_read_lock - mark the beginning of an RCU read-side critical section.
   61.15 -diff -pruN ../orig-linux-2.6.16.29/kernel/rcupdate.c ./kernel/rcupdate.c
   61.16 ---- ../orig-linux-2.6.16.29/kernel/rcupdate.c	2006-09-12 19:02:10.000000000 +0100
   61.17 -+++ ./kernel/rcupdate.c	2006-09-19 14:05:39.000000000 +0100
   61.18 -@@ -485,6 +485,20 @@ int rcu_pending(int cpu)
   61.19 - 		__rcu_pending(&rcu_bh_ctrlblk, &per_cpu(rcu_bh_data, cpu));
   61.20 - }
   61.21 - 
   61.22 -+/*
   61.23 -+ * Check to see if any future RCU-related work will need to be done
   61.24 -+ * by the current CPU, even if none need be done immediately, returning
   61.25 -+ * 1 if so.  This function is part of the RCU implementation; it is -not-
   61.26 -+ * an exported member of the RCU API.
   61.27 -+ */
   61.28 -+int rcu_needs_cpu(int cpu)
   61.29 -+{
   61.30 -+	struct rcu_data *rdp = &per_cpu(rcu_data, cpu);
   61.31 -+	struct rcu_data *rdp_bh = &per_cpu(rcu_bh_data, cpu);
   61.32 -+
   61.33 -+	return (!!rdp->curlist || !!rdp_bh->curlist || rcu_pending(cpu));
   61.34 -+}
   61.35 -+
   61.36 - void rcu_check_callbacks(int cpu, int user)
   61.37 - {
   61.38 - 	if (user || 
    62.1 --- a/patches/linux-2.6.16.29/rename-TSS_sysenter_esp0-SYSENTER_stack_esp0.patch	Mon Nov 27 10:10:57 2006 -0700
    62.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    62.3 @@ -1,30 +0,0 @@
    62.4 -diff -pruN ../orig-linux-2.6.16.29/arch/i386/kernel/entry.S ./arch/i386/kernel/entry.S
    62.5 ---- ../orig-linux-2.6.16.29/arch/i386/kernel/entry.S	2006-09-12 19:02:10.000000000 +0100
    62.6 -+++ ./arch/i386/kernel/entry.S	2006-09-19 14:05:44.000000000 +0100
    62.7 -@@ -177,7 +177,7 @@ need_resched:
    62.8 - 
    62.9 - 	# sysenter call handler stub
   62.10 - ENTRY(sysenter_entry)
   62.11 --	movl TSS_sysenter_esp0(%esp),%esp
   62.12 -+	movl SYSENTER_stack_esp0(%esp),%esp
   62.13 - sysenter_past_esp:
   62.14 - 	sti
   62.15 - 	pushl $(__USER_DS)
   62.16 -@@ -492,7 +492,7 @@ device_not_available_emulate:
   62.17 -  * that sets up the real kernel stack. Check here, since we can't
   62.18 -  * allow the wrong stack to be used.
   62.19 -  *
   62.20 -- * "TSS_sysenter_esp0+12" is because the NMI/debug handler will have
   62.21 -+ * "SYSENTER_stack_esp0+12" is because the NMI/debug handler will have
   62.22 -  * already pushed 3 words if it hits on the sysenter instruction:
   62.23 -  * eflags, cs and eip.
   62.24 -  *
   62.25 -@@ -504,7 +504,7 @@ device_not_available_emulate:
   62.26 - 	cmpw $__KERNEL_CS,4(%esp);		\
   62.27 - 	jne ok;					\
   62.28 - label:						\
   62.29 --	movl TSS_sysenter_esp0+offset(%esp),%esp;	\
   62.30 -+	movl SYSENTER_stack_esp0+offset(%esp),%esp;	\
   62.31 - 	pushfl;					\
   62.32 - 	pushl $__KERNEL_CS;			\
   62.33 - 	pushl $sysenter_past_esp
    63.1 --- a/patches/linux-2.6.16.29/series	Mon Nov 27 10:10:57 2006 -0700
    63.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    63.3 @@ -1,25 +0,0 @@
    63.4 -blktap-aio-16_03_06.patch
    63.5 -device_bind.patch
    63.6 -fix-hz-suspend.patch
    63.7 -fix-ide-cd-pio-mode.patch
    63.8 -i386-mach-io-check-nmi.patch
    63.9 -ipv6-no-autoconf.patch
   63.10 -net-csum.patch
   63.11 -net-gso-0-base.patch
   63.12 -net-gso-1-check-dodgy.patch
   63.13 -net-gso-2-checksum-fix.patch
   63.14 -net-gso-3-fix-errorcheck.patch
   63.15 -net-gso-4-kill-warnon.patch
   63.16 -net-gso-5-rcv-mss.patch
   63.17 -pci-mmconfig-fix-from-2.6.17.patch
   63.18 -pmd-shared.patch
   63.19 -rcu_needs_cpu.patch
   63.20 -rename-TSS_sysenter_esp0-SYSENTER_stack_esp0.patch
   63.21 -smp-alts.patch
   63.22 -tpm_plugin_2.6.17.patch
   63.23 -x86-increase-interrupt-vector-range.patch
   63.24 -xen-hotplug.patch
   63.25 -xenoprof-generic.patch
   63.26 -x86-put-note-sections-into-a-pt_note-segment-in-vmlinux.patch
   63.27 -x86_64-put-note-sections-into-a-pt_note-segment-in-vmlinux.patch
   63.28 -x86-elfnote-as-preprocessor-macro.patch
    64.1 --- a/patches/linux-2.6.16.29/smp-alts.patch	Mon Nov 27 10:10:57 2006 -0700
    64.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    64.3 @@ -1,591 +0,0 @@
    64.4 -diff -pruN ../orig-linux-2.6.16.29/arch/i386/Kconfig ./arch/i386/Kconfig
    64.5 ---- ../orig-linux-2.6.16.29/arch/i386/Kconfig	2006-09-12 19:02:10.000000000 +0100
    64.6 -+++ ./arch/i386/Kconfig	2006-09-19 14:05:48.000000000 +0100
    64.7 -@@ -202,6 +202,19 @@ config SMP
    64.8 - 
    64.9 - 	  If you don't know what to do here, say N.
   64.10 - 
   64.11 -+config SMP_ALTERNATIVES
   64.12 -+	bool "SMP alternatives support (EXPERIMENTAL)"
   64.13 -+	depends on SMP && EXPERIMENTAL
   64.14 -+	help
   64.15 -+	  Try to reduce the overhead of running an SMP kernel on a uniprocessor
   64.16 -+	  host slightly by replacing certain key instruction sequences
   64.17 -+	  according to whether we currently have more than one CPU available.
   64.18 -+	  This should provide a noticeable boost to performance when
   64.19 -+	  running SMP kernels on UP machines, and have negligible impact
   64.20 -+	  when running on an true SMP host.
   64.21 -+
   64.22 -+          If unsure, say N.
   64.23 -+	  
   64.24 - config NR_CPUS
   64.25 - 	int "Maximum number of CPUs (2-255)"
   64.26 - 	range 2 255
   64.27 -diff -pruN ../orig-linux-2.6.16.29/arch/i386/kernel/Makefile ./arch/i386/kernel/Makefile
   64.28 ---- ../orig-linux-2.6.16.29/arch/i386/kernel/Makefile	2006-09-12 19:02:10.000000000 +0100
   64.29 -+++ ./arch/i386/kernel/Makefile	2006-09-19 14:05:48.000000000 +0100
   64.30 -@@ -37,6 +37,7 @@ obj-$(CONFIG_EFI) 		+= efi.o efi_stub.o
   64.31 - obj-$(CONFIG_DOUBLEFAULT) 	+= doublefault.o
   64.32 - obj-$(CONFIG_VM86)		+= vm86.o
   64.33 - obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
   64.34 -+obj-$(CONFIG_SMP_ALTERNATIVES)  += smpalts.o
   64.35 - 
   64.36 - EXTRA_AFLAGS   := -traditional
   64.37 - 
   64.38 -diff -pruN ../orig-linux-2.6.16.29/arch/i386/kernel/smpalts.c ./arch/i386/kernel/smpalts.c
   64.39 ---- ../orig-linux-2.6.16.29/arch/i386/kernel/smpalts.c	1970-01-01 01:00:00.000000000 +0100
   64.40 -+++ ./arch/i386/kernel/smpalts.c	2006-09-19 14:05:48.000000000 +0100
   64.41 -@@ -0,0 +1,85 @@
   64.42 -+#include <linux/kernel.h>
   64.43 -+#include <asm/system.h>
   64.44 -+#include <asm/smp_alt.h>
   64.45 -+#include <asm/processor.h>
   64.46 -+#include <asm/string.h>
   64.47 -+
   64.48 -+struct smp_replacement_record {
   64.49 -+	unsigned char targ_size;
   64.50 -+	unsigned char smp1_size;
   64.51 -+	unsigned char smp2_size;
   64.52 -+	unsigned char up_size;
   64.53 -+	unsigned char feature;
   64.54 -+	unsigned char data[0];
   64.55 -+};
   64.56 -+
   64.57 -+struct smp_alternative_record {
   64.58 -+	void *targ_start;
   64.59 -+	struct smp_replacement_record *repl;
   64.60 -+};
   64.61 -+
   64.62 -+extern struct smp_alternative_record __start_smp_alternatives_table,
   64.63 -+  __stop_smp_alternatives_table;
   64.64 -+extern unsigned long __init_begin, __init_end;
   64.65 -+
   64.66 -+void prepare_for_smp(void)
   64.67 -+{
   64.68 -+	struct smp_alternative_record *r;
   64.69 -+	printk(KERN_INFO "Enabling SMP...\n");
   64.70 -+	for (r = &__start_smp_alternatives_table;
   64.71 -+	     r != &__stop_smp_alternatives_table;
   64.72 -+	     r++) {
   64.73 -+		BUG_ON(r->repl->targ_size < r->repl->smp1_size);
   64.74 -+		BUG_ON(r->repl->targ_size < r->repl->smp2_size);
   64.75 -+		BUG_ON(r->repl->targ_size < r->repl->up_size);
   64.76 -+               if (system_state == SYSTEM_RUNNING &&
   64.77 -+                   r->targ_start >= (void *)&__init_begin &&
   64.78 -+                   r->targ_start < (void *)&__init_end)
   64.79 -+                       continue;
   64.80 -+		if (r->repl->feature != (unsigned char)-1 &&
   64.81 -+		    boot_cpu_has(r->repl->feature)) {
   64.82 -+			memcpy(r->targ_start,
   64.83 -+			       r->repl->data + r->repl->smp1_size,
   64.84 -+			       r->repl->smp2_size);
   64.85 -+			memset(r->targ_start + r->repl->smp2_size,
   64.86 -+			       0x90,
   64.87 -+			       r->repl->targ_size - r->repl->smp2_size);
   64.88 -+		} else {
   64.89 -+			memcpy(r->targ_start,
   64.90 -+			       r->repl->data,
   64.91 -+			       r->repl->smp1_size);
   64.92 -+			memset(r->targ_start + r->repl->smp1_size,
   64.93 -+			       0x90,
   64.94 -+			       r->repl->targ_size - r->repl->smp1_size);
   64.95 -+		}
   64.96 -+	}
   64.97 -+	/* Paranoia */
   64.98 -+	asm volatile ("jmp 1f\n1:");
   64.99 -+	mb();
  64.100 -+}
  64.101 -+
  64.102 -+void unprepare_for_smp(void)
  64.103 -+{
  64.104 -+	struct smp_alternative_record *r;
  64.105 -+	printk(KERN_INFO "Disabling SMP...\n");
  64.106 -+	for (r = &__start_smp_alternatives_table;
  64.107 -+	     r != &__stop_smp_alternatives_table;
  64.108 -+	     r++) {
  64.109 -+		BUG_ON(r->repl->targ_size < r->repl->smp1_size);
  64.110 -+		BUG_ON(r->repl->targ_size < r->repl->smp2_size);
  64.111 -+		BUG_ON(r->repl->targ_size < r->repl->up_size);
  64.112 -+               if (system_state == SYSTEM_RUNNING &&
  64.113 -+                   r->targ_start >= (void *)&__init_begin &&
  64.114 -+                   r->targ_start < (void *)&__init_end)
  64.115 -+                       continue;
  64.116 -+		memcpy(r->targ_start,
  64.117 -+		       r->repl->data + r->repl->smp1_size + r->repl->smp2_size,
  64.118 -+		       r->repl->up_size);
  64.119 -+		memset(r->targ_start + r->repl->up_size,
  64.120 -+		       0x90,
  64.121 -+		       r->repl->targ_size - r->repl->up_size);
  64.122 -+	}
  64.123 -+	/* Paranoia */
  64.124 -+	asm volatile ("jmp 1f\n1:");
  64.125 -+	mb();
  64.126 -+}
  64.127 -diff -pruN ../orig-linux-2.6.16.29/arch/i386/kernel/smpboot.c ./arch/i386/kernel/smpboot.c
  64.128 ---- ../orig-linux-2.6.16.29/arch/i386/kernel/smpboot.c	2006-09-12 19:02:10.000000000 +0100
  64.129 -+++ ./arch/i386/kernel/smpboot.c	2006-09-19 14:05:48.000000000 +0100
  64.130 -@@ -1218,6 +1218,11 @@ static void __init smp_boot_cpus(unsigne
  64.131 - 		if (max_cpus <= cpucount+1)
  64.132 - 			continue;
  64.133 - 
  64.134 -+#ifdef CONFIG_SMP_ALTERNATIVES
  64.135 -+		if (kicked == 1)
  64.136 -+			prepare_for_smp();
  64.137 -+#endif
  64.138 -+
  64.139 - 		if (((cpu = alloc_cpu_id()) <= 0) || do_boot_cpu(apicid, cpu))
  64.140 - 			printk("CPU #%d not responding - cannot use it.\n",
  64.141 - 								apicid);
  64.142 -@@ -1396,6 +1401,11 @@ int __devinit __cpu_up(unsigned int cpu)
  64.143 - 		return -EIO;
  64.144 - 	}
  64.145 - 
  64.146 -+#ifdef CONFIG_SMP_ALTERNATIVES
  64.147 -+	if (num_online_cpus() == 1)
  64.148 -+		prepare_for_smp();
  64.149 -+#endif
  64.150 -+
  64.151 - 	local_irq_enable();
  64.152 - 	per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
  64.153 - 	/* Unleash the CPU! */
  64.154 -diff -pruN ../orig-linux-2.6.16.29/arch/i386/kernel/vmlinux.lds.S ./arch/i386/kernel/vmlinux.lds.S
  64.155 ---- ../orig-linux-2.6.16.29/arch/i386/kernel/vmlinux.lds.S	2006-09-12 19:02:10.000000000 +0100
  64.156 -+++ ./arch/i386/kernel/vmlinux.lds.S	2006-09-19 14:05:48.000000000 +0100
  64.157 -@@ -34,6 +34,13 @@ SECTIONS
  64.158 -   __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { *(__ex_table) }
  64.159 -   __stop___ex_table = .;
  64.160 - 
  64.161 -+  . = ALIGN(16);
  64.162 -+  __start_smp_alternatives_table = .;
  64.163 -+  __smp_alternatives : { *(__smp_alternatives) }
  64.164 -+  __stop_smp_alternatives_table = .;
  64.165 -+
  64.166 -+  __smp_replacements : { *(__smp_replacements) }
  64.167 -+
  64.168 -   RODATA
  64.169 - 
  64.170 -   /* writeable */
  64.171 -diff -pruN ../orig-linux-2.6.16.29/include/asm-i386/atomic.h ./include/asm-i386/atomic.h
  64.172 ---- ../orig-linux-2.6.16.29/include/asm-i386/atomic.h	2006-09-12 19:02:10.000000000 +0100
  64.173 -+++ ./include/asm-i386/atomic.h	2006-09-19 14:05:48.000000000 +0100
  64.174 -@@ -4,18 +4,13 @@
  64.175 - #include <linux/config.h>
  64.176 - #include <linux/compiler.h>
  64.177 - #include <asm/processor.h>
  64.178 -+#include <asm/smp_alt.h>
  64.179 - 
  64.180 - /*
  64.181 -  * Atomic operations that C can't guarantee us.  Useful for
  64.182 -  * resource counting etc..
  64.183 -  */
  64.184 - 
  64.185 --#ifdef CONFIG_SMP
  64.186 --#define LOCK "lock ; "
  64.187 --#else
  64.188 --#define LOCK ""
  64.189 --#endif
  64.190 --
  64.191 - /*
  64.192 -  * Make sure gcc doesn't try to be clever and move things around
  64.193 -  * on us. We need to use _exactly_ the address the user gave us,
  64.194 -diff -pruN ../orig-linux-2.6.16.29/include/asm-i386/bitops.h ./include/asm-i386/bitops.h
  64.195 ---- ../orig-linux-2.6.16.29/include/asm-i386/bitops.h	2006-09-12 19:02:10.000000000 +0100
  64.196 -+++ ./include/asm-i386/bitops.h	2006-09-19 14:05:48.000000000 +0100
  64.197 -@@ -7,6 +7,7 @@
  64.198 - 
  64.199 - #include <linux/config.h>
  64.200 - #include <linux/compiler.h>
  64.201 -+#include <asm/smp_alt.h>
  64.202 - 
  64.203 - /*
  64.204 -  * These have to be done with inline assembly: that way the bit-setting
  64.205 -@@ -16,12 +17,6 @@
  64.206 -  * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
  64.207 -  */
  64.208 - 
  64.209 --#ifdef CONFIG_SMP
  64.210 --#define LOCK_PREFIX "lock ; "
  64.211 --#else
  64.212 --#define LOCK_PREFIX ""
  64.213 --#endif
  64.214 --
  64.215 - #define ADDR (*(volatile long *) addr)
  64.216 - 
  64.217 - /**
  64.218 -@@ -41,7 +36,7 @@
  64.219 -  */
  64.220 - static inline void set_bit(int nr, volatile unsigned long * addr)
  64.221 - {
  64.222 --	__asm__ __volatile__( LOCK_PREFIX
  64.223 -+	__asm__ __volatile__( LOCK
  64.224 - 		"btsl %1,%0"
  64.225 - 		:"+m" (ADDR)
  64.226 - 		:"Ir" (nr));
  64.227 -@@ -76,7 +71,7 @@ static inline void __set_bit(int nr, vol
  64.228 -  */
  64.229 - static inline void clear_bit(int nr, volatile unsigned long * addr)
  64.230 - {
  64.231 --	__asm__ __volatile__( LOCK_PREFIX
  64.232 -+	__asm__ __volatile__( LOCK
  64.233 - 		"btrl %1,%0"
  64.234 - 		:"+m" (ADDR)
  64.235 - 		:"Ir" (nr));
  64.236 -@@ -121,7 +116,7 @@ static inline void __change_bit(int nr, 
  64.237 -  */
  64.238 - static inline void change_bit(int nr, volatile unsigned long * addr)
  64.239 - {
  64.240 --	__asm__ __volatile__( LOCK_PREFIX
  64.241 -+	__asm__ __volatile__( LOCK
  64.242 - 		"btcl %1,%0"
  64.243 - 		:"+m" (ADDR)
  64.244 - 		:"Ir" (nr));
  64.245 -@@ -140,7 +135,7 @@ static inline int test_and_set_bit(int n
  64.246 - {
  64.247 - 	int oldbit;
  64.248 - 
  64.249 --	__asm__ __volatile__( LOCK_PREFIX
  64.250 -+	__asm__ __volatile__( LOCK
  64.251 - 		"btsl %2,%1\n\tsbbl %0,%0"
  64.252 - 		:"=r" (oldbit),"+m" (ADDR)
  64.253 - 		:"Ir" (nr) : "memory");
  64.254 -@@ -180,7 +175,7 @@ static inline int test_and_clear_bit(int
  64.255 - {
  64.256 - 	int oldbit;
  64.257 - 
  64.258 --	__asm__ __volatile__( LOCK_PREFIX
  64.259 -+	__asm__ __volatile__( LOCK
  64.260 - 		"btrl %2,%1\n\tsbbl %0,%0"
  64.261 - 		:"=r" (oldbit),"+m" (ADDR)
  64.262 - 		:"Ir" (nr) : "memory");
  64.263 -@@ -231,7 +226,7 @@ static inline int test_and_change_bit(in
  64.264 - {
  64.265 - 	int oldbit;
  64.266 - 
  64.267 --	__asm__ __volatile__( LOCK_PREFIX
  64.268 -+	__asm__ __volatile__( LOCK
  64.269 - 		"btcl %2,%1\n\tsbbl %0,%0"
  64.270 - 		:"=r" (oldbit),"+m" (ADDR)
  64.271 - 		:"Ir" (nr) : "memory");
  64.272 -diff -pruN ../orig-linux-2.6.16.29/include/asm-i386/futex.h ./include/asm-i386/futex.h
  64.273 ---- ../orig-linux-2.6.16.29/include/asm-i386/futex.h	2006-09-12 19:02:10.000000000 +0100
  64.274 -+++ ./include/asm-i386/futex.h	2006-09-19 14:05:48.000000000 +0100
  64.275 -@@ -28,7 +28,7 @@
  64.276 - "1:	movl	%2, %0\n\
  64.277 - 	movl	%0, %3\n"					\
  64.278 - 	insn "\n"						\
  64.279 --"2:	" LOCK_PREFIX "cmpxchgl %3, %2\n\
  64.280 -+"2:	" LOCK "cmpxchgl %3, %2\n\
  64.281 - 	jnz	1b\n\
  64.282 - 3:	.section .fixup,\"ax\"\n\
  64.283 - 4:	mov	%5, %1\n\
  64.284 -@@ -68,7 +68,7 @@ futex_atomic_op_inuser (int encoded_op, 
  64.285 - #endif
  64.286 - 		switch (op) {
  64.287 - 		case FUTEX_OP_ADD:
  64.288 --			__futex_atomic_op1(LOCK_PREFIX "xaddl %0, %2", ret,
  64.289 -+			__futex_atomic_op1(LOCK "xaddl %0, %2", ret,
  64.290 - 					   oldval, uaddr, oparg);
  64.291 - 			break;
  64.292 - 		case FUTEX_OP_OR:
  64.293 -diff -pruN ../orig-linux-2.6.16.29/include/asm-i386/rwsem.h ./include/asm-i386/rwsem.h
  64.294 ---- ../orig-linux-2.6.16.29/include/asm-i386/rwsem.h	2006-09-12 19:02:10.000000000 +0100
  64.295 -+++ ./include/asm-i386/rwsem.h	2006-09-19 14:05:48.000000000 +0100
  64.296 -@@ -40,6 +40,7 @@
  64.297 - 
  64.298 - #include <linux/list.h>
  64.299 - #include <linux/spinlock.h>
  64.300 -+#include <asm/smp_alt.h>
  64.301 - 
  64.302 - struct rwsem_waiter;
  64.303 - 
  64.304 -@@ -99,7 +100,7 @@ static inline void __down_read(struct rw
  64.305 - {
  64.306 - 	__asm__ __volatile__(
  64.307 - 		"# beginning down_read\n\t"
  64.308 --LOCK_PREFIX	"  incl      (%%eax)\n\t" /* adds 0x00000001, returns the old value */
  64.309 -+LOCK	        "  incl      (%%eax)\n\t" /* adds 0x00000001, returns the old value */
  64.310 - 		"  js        2f\n\t" /* jump if we weren't granted the lock */
  64.311 - 		"1:\n\t"
  64.312 - 		LOCK_SECTION_START("")
  64.313 -@@ -130,7 +131,7 @@ static inline int __down_read_trylock(st
  64.314 - 		"  movl	     %1,%2\n\t"
  64.315 - 		"  addl      %3,%2\n\t"
  64.316 - 		"  jle	     2f\n\t"
  64.317 --LOCK_PREFIX	"  cmpxchgl  %2,%0\n\t"
  64.318 -+LOCK	        "  cmpxchgl  %2,%0\n\t"
  64.319 - 		"  jnz	     1b\n\t"
  64.320 - 		"2:\n\t"
  64.321 - 		"# ending __down_read_trylock\n\t"
  64.322 -@@ -150,7 +151,7 @@ static inline void __down_write(struct r
  64.323 - 	tmp = RWSEM_ACTIVE_WRITE_BIAS;
  64.324 - 	__asm__ __volatile__(
  64.325 - 		"# beginning down_write\n\t"
  64.326 --LOCK_PREFIX	"  xadd      %%edx,(%%eax)\n\t" /* subtract 0x0000ffff, returns the old value */
  64.327 -+LOCK	        "  xadd      %%edx,(%%eax)\n\t" /* subtract 0x0000ffff, returns the old value */
  64.328 - 		"  testl     %%edx,%%edx\n\t" /* was the count 0 before? */
  64.329 - 		"  jnz       2f\n\t" /* jump if we weren't granted the lock */
  64.330 - 		"1:\n\t"
  64.331 -@@ -188,7 +189,7 @@ static inline void __up_read(struct rw_s
  64.332 - 	__s32 tmp = -RWSEM_ACTIVE_READ_BIAS;
  64.333 - 	__asm__ __volatile__(
  64.334 - 		"# beginning __up_read\n\t"
  64.335 --LOCK_PREFIX	"  xadd      %%edx,(%%eax)\n\t" /* subtracts 1, returns the old value */
  64.336 -+LOCK	        "  xadd      %%edx,(%%eax)\n\t" /* subtracts 1, returns the old value */
  64.337 - 		"  js        2f\n\t" /* jump if the lock is being waited upon */
  64.338 - 		"1:\n\t"
  64.339 - 		LOCK_SECTION_START("")
  64.340 -@@ -214,7 +215,7 @@ static inline void __up_write(struct rw_
  64.341 - 	__asm__ __volatile__(
  64.342 - 		"# beginning __up_write\n\t"
  64.343 - 		"  movl      %2,%%edx\n\t"
  64.344 --LOCK_PREFIX	"  xaddl     %%edx,(%%eax)\n\t" /* tries to transition 0xffff0001 -> 0x00000000 */
  64.345 -+LOCK	        "  xaddl     %%edx,(%%eax)\n\t" /* tries to transition 0xffff0001 -> 0x00000000 */
  64.346 - 		"  jnz       2f\n\t" /* jump if the lock is being waited upon */
  64.347 - 		"1:\n\t"
  64.348 - 		LOCK_SECTION_START("")
  64.349 -@@ -239,7 +240,7 @@ static inline void __downgrade_write(str
  64.350 - {
  64.351 - 	__asm__ __volatile__(
  64.352 - 		"# beginning __downgrade_write\n\t"
  64.353 --LOCK_PREFIX	"  addl      %2,(%%eax)\n\t" /* transitions 0xZZZZ0001 -> 0xYYYY0001 */
  64.354 -+LOCK	        "  addl      %2,(%%eax)\n\t" /* transitions 0xZZZZ0001 -> 0xYYYY0001 */
  64.355 - 		"  js        2f\n\t" /* jump if the lock is being waited upon */
  64.356 - 		"1:\n\t"
  64.357 - 		LOCK_SECTION_START("")
  64.358 -@@ -263,7 +264,7 @@ LOCK_PREFIX	"  addl      %2,(%%eax)\n\t"
  64.359 - static inline void rwsem_atomic_add(int delta, struct rw_semaphore *sem)
  64.360 - {
  64.361 - 	__asm__ __volatile__(
  64.362 --LOCK_PREFIX	"addl %1,%0"
  64.363 -+LOCK	          "addl %1,%0"
  64.364 - 		: "=m"(sem->count)
  64.365 - 		: "ir"(delta), "m"(sem->count));
  64.366 - }
  64.367 -@@ -276,7 +277,7 @@ static inline int rwsem_atomic_update(in
  64.368 - 	int tmp = delta;
  64.369 - 
  64.370 - 	__asm__ __volatile__(
  64.371 --LOCK_PREFIX	"xadd %0,(%2)"
  64.372 -+LOCK  	          "xadd %0,(%2)"
  64.373 - 		: "+r"(tmp), "=m"(sem->count)
  64.374 - 		: "r"(sem), "m"(sem->count)
  64.375 - 		: "memory");
  64.376 -diff -pruN ../orig-linux-2.6.16.29/include/asm-i386/smp_alt.h ./include/asm-i386/smp_alt.h
  64.377 ---- ../orig-linux-2.6.16.29/include/asm-i386/smp_alt.h	1970-01-01 01:00:00.000000000 +0100
  64.378 -+++ ./include/asm-i386/smp_alt.h	2006-09-19 14:05:48.000000000 +0100
  64.379 -@@ -0,0 +1,32 @@
  64.380 -+#ifndef __ASM_SMP_ALT_H__
  64.381 -+#define __ASM_SMP_ALT_H__
  64.382 -+
  64.383 -+#include <linux/config.h>
  64.384 -+
  64.385 -+#ifdef CONFIG_SMP
  64.386 -+#if defined(CONFIG_SMP_ALTERNATIVES) && !defined(MODULE)
  64.387 -+#define LOCK \
  64.388 -+        "6677: nop\n" \
  64.389 -+	".section __smp_alternatives,\"a\"\n" \
  64.390 -+	".long 6677b\n" \
  64.391 -+	".long 6678f\n" \
  64.392 -+	".previous\n" \
  64.393 -+	".section __smp_replacements,\"a\"\n" \
  64.394 -+	"6678: .byte 1\n" \
  64.395 -+	".byte 1\n" \
  64.396 -+	".byte 0\n" \
  64.397 -+        ".byte 1\n" \
  64.398 -+	".byte -1\n" \
  64.399 -+	"lock\n" \
  64.400 -+	"nop\n" \
  64.401 -+	".previous\n"
  64.402 -+void prepare_for_smp(void);
  64.403 -+void unprepare_for_smp(void);
  64.404 -+#else
  64.405 -+#define LOCK "lock ; "
  64.406 -+#endif
  64.407 -+#else
  64.408 -+#define LOCK ""
  64.409 -+#endif
  64.410 -+
  64.411 -+#endif /* __ASM_SMP_ALT_H__ */
  64.412 -diff -pruN ../orig-linux-2.6.16.29/include/asm-i386/spinlock.h ./include/asm-i386/spinlock.h
  64.413 ---- ../orig-linux-2.6.16.29/include/asm-i386/spinlock.h	2006-09-12 19:02:10.000000000 +0100
  64.414 -+++ ./include/asm-i386/spinlock.h	2006-09-19 14:05:48.000000000 +0100
  64.415 -@@ -6,6 +6,7 @@
  64.416 - #include <asm/page.h>
  64.417 - #include <linux/config.h>
  64.418 - #include <linux/compiler.h>
  64.419 -+#include <asm/smp_alt.h>
  64.420 - 
  64.421 - /*
  64.422 -  * Your basic SMP spinlocks, allowing only a single CPU anywhere
  64.423 -@@ -23,7 +24,8 @@
  64.424 - 
  64.425 - #define __raw_spin_lock_string \
  64.426 - 	"\n1:\t" \
  64.427 --	"lock ; decb %0\n\t" \
  64.428 -+	LOCK \
  64.429 -+	"decb %0\n\t" \
  64.430 - 	"jns 3f\n" \
  64.431 - 	"2:\t" \
  64.432 - 	"rep;nop\n\t" \
  64.433 -@@ -34,7 +36,8 @@
  64.434 - 
  64.435 - #define __raw_spin_lock_string_flags \
  64.436 - 	"\n1:\t" \
  64.437 --	"lock ; decb %0\n\t" \
  64.438 -+	LOCK \
  64.439 -+	"decb %0\n\t" \
  64.440 - 	"jns 4f\n\t" \
  64.441 - 	"2:\t" \
  64.442 - 	"testl $0x200, %1\n\t" \
  64.443 -@@ -65,10 +68,34 @@ static inline void __raw_spin_lock_flags
  64.444 - static inline int __raw_spin_trylock(raw_spinlock_t *lock)
  64.445 - {
  64.446 - 	char oldval;
  64.447 -+#ifdef CONFIG_SMP_ALTERNATIVES
  64.448 - 	__asm__ __volatile__(
  64.449 --		"xchgb %b0,%1"
  64.450 -+		"1:movb %1,%b0\n"
  64.451 -+		"movb $0,%1\n"
  64.452 -+		"2:"
  64.453 -+		".section __smp_alternatives,\"a\"\n"
  64.454 -+		".long 1b\n"
  64.455 -+		".long 3f\n"
  64.456 -+		".previous\n"
  64.457 -+		".section __smp_replacements,\"a\"\n"
  64.458 -+		"3: .byte 2b - 1b\n"
  64.459 -+		".byte 5f-4f\n"
  64.460 -+		".byte 0\n"
  64.461 -+		".byte 6f-5f\n"
  64.462 -+		".byte -1\n"
  64.463 -+		"4: xchgb %b0,%1\n"
  64.464 -+		"5: movb %1,%b0\n"
  64.465 -+		"movb $0,%1\n"
  64.466 -+		"6:\n"
  64.467 -+		".previous\n"
  64.468 - 		:"=q" (oldval), "=m" (lock->slock)
  64.469 - 		:"0" (0) : "memory");
  64.470 -+#else
  64.471 -+	__asm__ __volatile__(
  64.472 -+		"xchgb %b0,%1\n"
  64.473 -+		:"=q" (oldval), "=m" (lock->slock)
  64.474 -+		:"0" (0) : "memory");
  64.475 -+#endif
  64.476 - 	return oldval > 0;
  64.477 - }
  64.478 - 
  64.479 -@@ -178,12 +205,12 @@ static inline int __raw_write_trylock(ra
  64.480 - 
  64.481 - static inline void __raw_read_unlock(raw_rwlock_t *rw)
  64.482 - {
  64.483 --	asm volatile("lock ; incl %0" :"=m" (rw->lock) : : "memory");
  64.484 -+	asm volatile(LOCK "incl %0" :"=m" (rw->lock) : : "memory");
  64.485 - }
  64.486 - 
  64.487 - static inline void __raw_write_unlock(raw_rwlock_t *rw)
  64.488 - {
  64.489 --	asm volatile("lock ; addl $" RW_LOCK_BIAS_STR ", %0"
  64.490 -+	asm volatile(LOCK "addl $" RW_LOCK_BIAS_STR ", %0"
  64.491 - 				 : "=m" (rw->lock) : : "memory");
  64.492 - }
  64.493 - 
  64.494 -diff -pruN ../orig-linux-2.6.16.29/include/asm-i386/system.h ./include/asm-i386/system.h
  64.495 ---- ../orig-linux-2.6.16.29/include/asm-i386/system.h	2006-09-12 19:02:10.000000000 +0100
  64.496 -+++ ./include/asm-i386/system.h	2006-09-19 14:05:48.000000000 +0100
  64.497 -@@ -5,7 +5,7 @@
  64.498 - #include <linux/kernel.h>
  64.499 - #include <asm/segment.h>
  64.500 - #include <asm/cpufeature.h>
  64.501 --#include <linux/bitops.h> /* for LOCK_PREFIX */
  64.502 -+#include <asm/smp_alt.h>
  64.503 - 
  64.504 - #ifdef __KERNEL__
  64.505 - 
  64.506 -@@ -271,19 +271,19 @@ static inline unsigned long __cmpxchg(vo
  64.507 - 	unsigned long prev;
  64.508 - 	switch (size) {
  64.509 - 	case 1:
  64.510 --		__asm__ __volatile__(LOCK_PREFIX "cmpxchgb %b1,%2"
  64.511 -+		__asm__ __volatile__(LOCK "cmpxchgb %b1,%2"
  64.512 - 				     : "=a"(prev)
  64.513 - 				     : "q"(new), "m"(*__xg(ptr)), "0"(old)
  64.514 - 				     : "memory");
  64.515 - 		return prev;
  64.516 - 	case 2:
  64.517 --		__asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2"
  64.518 -+		__asm__ __volatile__(LOCK "cmpxchgw %w1,%2"
  64.519 - 				     : "=a"(prev)
  64.520 - 				     : "r"(new), "m"(*__xg(ptr)), "0"(old)
  64.521 - 				     : "memory");
  64.522 - 		return prev;
  64.523 - 	case 4:
  64.524 --		__asm__ __volatile__(LOCK_PREFIX "cmpxchgl %1,%2"
  64.525 -+		__asm__ __volatile__(LOCK "cmpxchgl %1,%2"
  64.526 - 				     : "=a"(prev)
  64.527 - 				     : "r"(new), "m"(*__xg(ptr)), "0"(old)
  64.528 - 				     : "memory");
  64.529 -@@ -336,7 +336,7 @@ static inline unsigned long long __cmpxc
  64.530 - 				      unsigned long long new)
  64.531 - {
  64.532 - 	unsigned long long prev;
  64.533 --	__asm__ __volatile__(LOCK_PREFIX "cmpxchg8b %3"
  64.534 -+	__asm__ __volatile__(LOCK "cmpxchg8b %3"
  64.535 - 			     : "=A"(prev)
  64.536 - 			     : "b"((unsigned long)new),
  64.537 - 			       "c"((unsigned long)(new >> 32)),
  64.538 -@@ -503,11 +503,55 @@ struct alt_instr { 
  64.539 - #endif
  64.540 - 
  64.541 - #ifdef CONFIG_SMP
  64.542 -+#if defined(CONFIG_SMP_ALTERNATIVES) && !defined(MODULE)
  64.543 -+#define smp_alt_mb(instr)                                           \
  64.544 -+__asm__ __volatile__("6667:\nnop\nnop\nnop\nnop\nnop\nnop\n6668:\n" \
  64.545 -+		     ".section __smp_alternatives,\"a\"\n"          \
  64.546 -+		     ".long 6667b\n"                                \
  64.547 -+                     ".long 6673f\n"                                \
  64.548 -+		     ".previous\n"                                  \
  64.549 -+		     ".section __smp_replacements,\"a\"\n"          \
  64.550 -+		     "6673:.byte 6668b-6667b\n"                     \
  64.551 -+		     ".byte 6670f-6669f\n"                          \
  64.552 -+		     ".byte 6671f-6670f\n"                          \
  64.553 -+                     ".byte 0\n"                                    \
  64.554 -+		     ".byte %c0\n"                                  \
  64.555 -+		     "6669:lock;addl $0,0(%%esp)\n"                 \
  64.556 -+		     "6670:" instr "\n"                             \
  64.557 -+		     "6671:\n"                                      \
  64.558 -+		     ".previous\n"                                  \
  64.559 -+		     :                                              \
  64.560 -+		     : "i" (X86_FEATURE_XMM2)                       \
  64.561 -+		     : "memory")
  64.562 -+#define smp_rmb() smp_alt_mb("lfence")
  64.563 -+#define smp_mb()  smp_alt_mb("mfence")
  64.564 -+#define set_mb(var, value) do {                                     \
  64.565 -+unsigned long __set_mb_temp;                                        \
  64.566 -+__asm__ __volatile__("6667:movl %1, %0\n6668:\n"                    \
  64.567 -+		     ".section __smp_alternatives,\"a\"\n"          \
  64.568 -+		     ".long 6667b\n"                                \
  64.569 -+		     ".long 6673f\n"                                \
  64.570 -+		     ".previous\n"                                  \
  64.571 -+		     ".section __smp_replacements,\"a\"\n"          \
  64.572 -+		     "6673: .byte 6668b-6667b\n"                    \
  64.573 -+		     ".byte 6670f-6669f\n"                          \
  64.574 -+		     ".byte 0\n"                                    \
  64.575 -+		     ".byte 6671f-6670f\n"                          \
  64.576 -+		     ".byte -1\n"                                   \
  64.577 -+		     "6669: xchg %1, %0\n"                          \
  64.578 -+		     "6670:movl %1, %0\n"                           \
  64.579 -+		     "6671:\n"                                      \
  64.580 -+		     ".previous\n"                                  \
  64.581 -+		     : "=m" (var), "=r" (__set_mb_temp)             \
  64.582 -+		     : "1" (value)                                  \
  64.583 -+		     : "memory"); } while (0)
  64.584 -+#else
  64.585 - #define smp_mb()	mb()
  64.586 - #define smp_rmb()	rmb()
  64.587 -+#define set_mb(var, value) do { (void) xchg(&var, value); } while (0)
  64.588 -+#endif
  64.589 - #define smp_wmb()	wmb()
  64.590 - #define smp_read_barrier_depends()	read_barrier_depends()
  64.591 --#define set_mb(var, value) do { (void) xchg(&var, value); } while (0)
  64.592 - #else
  64.593 - #define smp_mb()	barrier()
  64.594 - #define smp_rmb()	barrier()
    65.1 --- a/patches/linux-2.6.16.29/tpm_plugin_2.6.17.patch	Mon Nov 27 10:10:57 2006 -0700
    65.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    65.3 @@ -1,1545 +0,0 @@
    65.4 -diff -pruN ../orig-linux-2.6.16.29/drivers/char/tpm/tpm_atmel.c ./drivers/char/tpm/tpm_atmel.c
    65.5 ---- ../orig-linux-2.6.16.29/drivers/char/tpm/tpm_atmel.c	2006-09-12 19:02:10.000000000 +0100
    65.6 -+++ ./drivers/char/tpm/tpm_atmel.c	2006-09-19 14:05:52.000000000 +0100
    65.7 -@@ -47,12 +47,12 @@ static int tpm_atml_recv(struct tpm_chip
    65.8 - 		return -EIO;
    65.9 - 
   65.10 - 	for (i = 0; i < 6; i++) {
   65.11 --		status = ioread8(chip->vendor->iobase + 1);
   65.12 -+		status = ioread8(chip->vendor.iobase + 1);
   65.13 - 		if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
   65.14 - 			dev_err(chip->dev, "error reading header\n");
   65.15 - 			return -EIO;
   65.16 - 		}
   65.17 --		*buf++ = ioread8(chip->vendor->iobase);
   65.18 -+		*buf++ = ioread8(chip->vendor.iobase);
   65.19 - 	}
   65.20 - 
   65.21 - 	/* size of the data received */
   65.22 -@@ -63,7 +63,7 @@ static int tpm_atml_recv(struct tpm_chip
   65.23 - 		dev_err(chip->dev,
   65.24 - 			"Recv size(%d) less than available space\n", size);
   65.25 - 		for (; i < size; i++) {	/* clear the waiting data anyway */
   65.26 --			status = ioread8(chip->vendor->iobase + 1);
   65.27 -+			status = ioread8(chip->vendor.iobase + 1);
   65.28 - 			if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
   65.29 - 				dev_err(chip->dev, "error reading data\n");
   65.30 - 				return -EIO;
   65.31 -@@ -74,16 +74,16 @@ static int tpm_atml_recv(struct tpm_chip
   65.32 - 
   65.33 - 	/* read all the data available */
   65.34 - 	for (; i < size; i++) {
   65.35 --		status = ioread8(chip->vendor->iobase + 1);
   65.36 -+		status = ioread8(chip->vendor.iobase + 1);
   65.37 - 		if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
   65.38 - 			dev_err(chip->dev, "error reading data\n");
   65.39 - 			return -EIO;
   65.40 - 		}
   65.41 --		*buf++ = ioread8(chip->vendor->iobase);
   65.42 -+		*buf++ = ioread8(chip->vendor.iobase);
   65.43 - 	}
   65.44 - 
   65.45 - 	/* make sure data available is gone */
   65.46 --	status = ioread8(chip->vendor->iobase + 1);
   65.47 -+	status = ioread8(chip->vendor.iobase + 1);
   65.48 - 
   65.49 - 	if (status & ATML_STATUS_DATA_AVAIL) {
   65.50 - 		dev_err(chip->dev, "data available is stuck\n");
   65.51 -@@ -100,7 +100,7 @@ static int tpm_atml_send(struct tpm_chip
   65.52 - 	dev_dbg(chip->dev, "tpm_atml_send:\n");
   65.53 - 	for (i = 0; i < count; i++) {
   65.54 - 		dev_dbg(chip->dev, "%d 0x%x(%d)\n",  i, buf[i], buf[i]);
   65.55 -- 		iowrite8(buf[i], chip->vendor->iobase);
   65.56 -+ 		iowrite8(buf[i], chip->vendor.iobase);
   65.57 - 	}
   65.58 - 
   65.59 - 	return count;
   65.60 -@@ -108,12 +108,12 @@ static int tpm_atml_send(struct tpm_chip
   65.61 - 
   65.62 - static void tpm_atml_cancel(struct tpm_chip *chip)
   65.63 - {
   65.64 --	iowrite8(ATML_STATUS_ABORT, chip->vendor->iobase + 1);
   65.65 -+	iowrite8(ATML_STATUS_ABORT, chip->vendor.iobase + 1);
   65.66 - }
   65.67 - 
   65.68 - static u8 tpm_atml_status(struct tpm_chip *chip)
   65.69 - {
   65.70 --	return ioread8(chip->vendor->iobase + 1);
   65.71 -+	return ioread8(chip->vendor.iobase + 1);
   65.72 - }
   65.73 - 
   65.74 - static struct file_operations atmel_ops = {
   65.75 -@@ -140,7 +140,7 @@ static struct attribute* atmel_attrs[] =
   65.76 - 
   65.77 - static struct attribute_group atmel_attr_grp = { .attrs = atmel_attrs };
   65.78 - 
   65.79 --static struct tpm_vendor_specific tpm_atmel = {
   65.80 -+static const struct tpm_vendor_specific tpm_atmel = {
   65.81 - 	.recv = tpm_atml_recv,
   65.82 - 	.send = tpm_atml_send,
   65.83 - 	.cancel = tpm_atml_cancel,
   65.84 -@@ -159,10 +159,10 @@ static void atml_plat_remove(void)
   65.85 - 	struct tpm_chip *chip = dev_get_drvdata(&pdev->dev);
   65.86 - 
   65.87 - 	if (chip) {
   65.88 --		if (chip->vendor->have_region)
   65.89 --			atmel_release_region(chip->vendor->base,
   65.90 --					     chip->vendor->region_size);
   65.91 --		atmel_put_base_addr(chip->vendor);
   65.92 -+		if (chip->vendor.have_region)
   65.93 -+			atmel_release_region(chip->vendor.base,
   65.94 -+					     chip->vendor.region_size);
   65.95 -+		atmel_put_base_addr(chip->vendor.iobase);
   65.96 - 		tpm_remove_hardware(chip->dev);
   65.97 - 		platform_device_unregister(pdev);
   65.98 - 	}
   65.99 -@@ -179,18 +179,22 @@ static struct device_driver atml_drv = {
  65.100 - static int __init init_atmel(void)
  65.101 - {
  65.102 - 	int rc = 0;
  65.103 -+	void __iomem *iobase = NULL;
  65.104 -+	int have_region, region_size;
  65.105 -+	unsigned long base;
  65.106 -+	struct  tpm_chip *chip;
  65.107 - 
  65.108 - 	driver_register(&atml_drv);
  65.109 - 
  65.110 --	if ((tpm_atmel.iobase = atmel_get_base_addr(&tpm_atmel)) == NULL) {
  65.111 -+	if ((iobase = atmel_get_base_addr(&base, &region_size)) == NULL) {
  65.112 - 		rc = -ENODEV;
  65.113 - 		goto err_unreg_drv;
  65.114 - 	}
  65.115 - 
  65.116 --	tpm_atmel.have_region =
  65.117 -+	have_region =
  65.118 - 	    (atmel_request_region
  65.119 --	     (tpm_atmel.base, tpm_atmel.region_size,
  65.120 --	      "tpm_atmel0") == NULL) ? 0 : 1;
  65.121 -+	     (tpm_atmel.base, region_size, "tpm_atmel0") == NULL) ? 0 : 1;
  65.122 -+
  65.123 - 
  65.124 - 	if (IS_ERR
  65.125 - 	    (pdev =
  65.126 -@@ -199,17 +203,25 @@ static int __init init_atmel(void)
  65.127 - 		goto err_rel_reg;
  65.128 - 	}
  65.129 - 
  65.130 --	if ((rc = tpm_register_hardware(&pdev->dev, &tpm_atmel)) < 0)
  65.131 -+	if (!(chip = tpm_register_hardware(&pdev->dev, &tpm_atmel))) {
  65.132 -+		rc = -ENODEV;
  65.133 - 		goto err_unreg_dev;
  65.134 -+	}
  65.135 -+
  65.136 -+	chip->vendor.iobase = iobase;
  65.137 -+	chip->vendor.base = base;
  65.138 -+	chip->vendor.have_region = have_region;
  65.139 -+	chip->vendor.region_size = region_size;
  65.140 -+
  65.141 - 	return 0;
  65.142 - 
  65.143 - err_unreg_dev:
  65.144 - 	platform_device_unregister(pdev);
  65.145 - err_rel_reg:
  65.146 --	atmel_put_base_addr(&tpm_atmel);
  65.147 --	if (tpm_atmel.have_region)
  65.148 --		atmel_release_region(tpm_atmel.base,
  65.149 --				     tpm_atmel.region_size);
  65.150 -+	atmel_put_base_addr(iobase);
  65.151 -+	if (have_region)
  65.152 -+		atmel_release_region(base,
  65.153 -+				     region_size);
  65.154 - err_unreg_drv:
  65.155 - 	driver_unregister(&atml_drv);
  65.156 - 	return rc;
  65.157 -diff -pruN ../orig-linux-2.6.16.29/drivers/char/tpm/tpm_atmel.h ./drivers/char/tpm/tpm_atmel.h
  65.158 ---- ../orig-linux-2.6.16.29/drivers/char/tpm/tpm_atmel.h	2006-09-12 19:02:10.000000000 +0100
  65.159 -+++ ./drivers/char/tpm/tpm_atmel.h	2006-09-19 14:05:52.000000000 +0100
  65.160 -@@ -28,13 +28,12 @@
  65.161 - #define atmel_request_region request_mem_region
  65.162 - #define atmel_release_region release_mem_region
  65.163 - 
  65.164 --static inline void atmel_put_base_addr(struct tpm_vendor_specific
  65.165 --					 *vendor)
  65.166 -+static inline void atmel_put_base_addr(void __iomem *iobase)
  65.167 - {
  65.168 --	iounmap(vendor->iobase);
  65.169 -+	iounmap(iobase);
  65.170 - }
  65.171 - 
  65.172 --static void __iomem * atmel_get_base_addr(struct tpm_vendor_specific *vendor)
  65.173 -+static void __iomem * atmel_get_base_addr(unsigned long *base, int *region_size)
  65.174 - {
  65.175 - 	struct device_node *dn;
  65.176 - 	unsigned long address, size;
  65.177 -@@ -71,9 +70,9 @@ static void __iomem * atmel_get_base_add
  65.178 - 	else
  65.179 - 		size = reg[naddrc];
  65.180 - 
  65.181 --	vendor->base = address;
  65.182 --	vendor->region_size = size;
  65.183 --	return ioremap(vendor->base, vendor->region_size);
  65.184 -+	*base = address;
  65.185 -+	*region_size = size;
  65.186 -+	return ioremap(*base, *region_size);
  65.187 - }
  65.188 - #else
  65.189 - #define atmel_getb(chip, offset) inb(chip->vendor->base + offset)
  65.190 -@@ -106,14 +105,12 @@ static int atmel_verify_tpm11(void)
  65.191 - 	return 0;
  65.192 - }
  65.193 - 
  65.194 --static inline void atmel_put_base_addr(struct tpm_vendor_specific
  65.195 --					 *vendor)
  65.196 -+static inline void atmel_put_base_addr(void __iomem *iobase)
  65.197 - {
  65.198 - }
  65.199 - 
  65.200 - /* Determine where to talk to device */
  65.201 --static void __iomem * atmel_get_base_addr(struct tpm_vendor_specific
  65.202 --					 *vendor)
  65.203 -+static void __iomem * atmel_get_base_addr(unsigned long *base, int *region_size)
  65.204 - {
  65.205 - 	int lo, hi;
  65.206 - 
  65.207 -@@ -123,9 +120,9 @@ static void __iomem * atmel_get_base_add
  65.208 - 	lo = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_LO);
  65.209 - 	hi = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_HI);
  65.210 - 
  65.211 --	vendor->base = (hi << 8) | lo;
  65.212 --	vendor->region_size = 2;
  65.213 -+	*base = (hi << 8) | lo;
  65.214 -+	*region_size = 2;
  65.215 - 
  65.216 --	return ioport_map(vendor->base, vendor->region_size);
  65.217 -+	return ioport_map(*base, *region_size);
  65.218 - }
  65.219 - #endif
  65.220 -diff -pruN ../orig-linux-2.6.16.29/drivers/char/tpm/tpm_bios.c ./drivers/char/tpm/tpm_bios.c
  65.221 ---- ../orig-linux-2.6.16.29/drivers/char/tpm/tpm_bios.c	2006-09-12 19:02:10.000000000 +0100
  65.222 -+++ ./drivers/char/tpm/tpm_bios.c	2006-09-19 14:05:52.000000000 +0100
  65.223 -@@ -29,6 +29,11 @@
  65.224 - #define MAX_TEXT_EVENT		1000	/* Max event string length */
  65.225 - #define ACPI_TCPA_SIG		"TCPA"	/* 0x41504354 /'TCPA' */
  65.226 - 
  65.227 -+enum bios_platform_class {
  65.228 -+	BIOS_CLIENT = 0x00,
  65.229 -+	BIOS_SERVER = 0x01,
  65.230 -+};
  65.231 -+
  65.232 - struct tpm_bios_log {
  65.233 - 	void *bios_event_log;
  65.234 - 	void *bios_event_log_end;
  65.235 -@@ -36,9 +41,18 @@ struct tpm_bios_log {
  65.236 - 
  65.237 - struct acpi_tcpa {
  65.238 - 	struct acpi_table_header hdr;
  65.239 --	u16 reserved;
  65.240 --	u32 log_max_len __attribute__ ((packed));
  65.241 --	u32 log_start_addr __attribute__ ((packed));
  65.242 -+	u16 platform_class;
  65.243 -+	union {
  65.244 -+		struct client_hdr {
  65.245 -+			u32 log_max_len __attribute__ ((packed));
  65.246 -+			u64 log_start_addr __attribute__ ((packed));
  65.247 -+		} client;
  65.248 -+		struct server_hdr {
  65.249 -+			u16 reserved;
  65.250 -+			u64 log_max_len __attribute__ ((packed));
  65.251 -+			u64 log_start_addr __attribute__ ((packed));
  65.252 -+		} server;
  65.253 -+	};
  65.254 - };
  65.255 - 
  65.256 - struct tcpa_event {
  65.257 -@@ -91,6 +105,12 @@ static const char* tcpa_event_type_strin
  65.258 - 	"Non-Host Info"
  65.259 - };
  65.260 - 
  65.261 -+struct tcpa_pc_event {
  65.262 -+	u32 event_id;
  65.263 -+	u32 event_size;
  65.264 -+	u8 event_data[0];
  65.265 -+};
  65.266 -+
  65.267 - enum tcpa_pc_event_ids {
  65.268 - 	SMBIOS = 1,
  65.269 - 	BIS_CERT,
  65.270 -@@ -100,14 +120,15 @@ enum tcpa_pc_event_ids {
  65.271 - 	NVRAM,
  65.272 - 	OPTION_ROM_EXEC,
  65.273 - 	OPTION_ROM_CONFIG,
  65.274 --	OPTION_ROM_MICROCODE,
  65.275 -+	OPTION_ROM_MICROCODE = 10,
  65.276 - 	S_CRTM_VERSION,
  65.277 - 	S_CRTM_CONTENTS,
  65.278 - 	POST_CONTENTS,
  65.279 -+	HOST_TABLE_OF_DEVICES,
  65.280 - };
  65.281 - 
  65.282 - static const char* tcpa_pc_event_id_strings[] = {
  65.283 --	""
  65.284 -+	"",
  65.285 - 	"SMBIOS",
  65.286 - 	"BIS Certificate",
  65.287 - 	"POST BIOS ",
  65.288 -@@ -116,10 +137,12 @@ static const char* tcpa_pc_event_id_stri
  65.289 - 	"NVRAM",
  65.290 - 	"Option ROM",
  65.291 - 	"Option ROM config",
  65.292 --	"Option ROM microcode",
  65.293 -+	"",
  65.294 -+	"Option ROM microcode ",
  65.295 - 	"S-CRTM Version",
  65.296 --	"S-CRTM Contents",
  65.297 --	"S-CRTM POST Contents",
  65.298 -+	"S-CRTM Contents ",
  65.299 -+	"POST Contents ",
  65.300 -+	"Table of Devices",
  65.301 - };
  65.302 - 
  65.303 - /* returns pointer to start of pos. entry of tcg log */
  65.304 -@@ -191,7 +214,7 @@ static int get_event_name(char *dest, st
  65.305 - 	const char *name = "";
  65.306 - 	char data[40] = "";
  65.307 - 	int i, n_len = 0, d_len = 0;
  65.308 --	u32 event_id;
  65.309 -+	struct tcpa_pc_event *pc_event;
  65.310 - 
  65.311 - 	switch(event->event_type) {
  65.312 - 	case PREBOOT:
  65.313 -@@ -220,31 +243,32 @@ static int get_event_name(char *dest, st
  65.314 - 		}
  65.315 - 		break;
  65.316 - 	case EVENT_TAG:
  65.317 --		event_id = be32_to_cpu(*((u32 *)event_entry));
  65.318 -+		pc_event = (struct tcpa_pc_event *)event_entry;
  65.319 - 
  65.320 - 		/* ToDo Row data -> Base64 */
  65.321 - 
  65.322 --		switch (event_id) {
  65.323 -+		switch (pc_event->event_id) {
  65.324 - 		case SMBIOS:
  65.325 - 		case BIS_CERT:
  65.326 - 		case CMOS:
  65.327 - 		case NVRAM:
  65.328 - 		case OPTION_ROM_EXEC:
  65.329 - 		case OPTION_ROM_CONFIG:
  65.330 --		case OPTION_ROM_MICROCODE:
  65.331 - 		case S_CRTM_VERSION:
  65.332 --		case S_CRTM_CONTENTS:
  65.333 --		case POST_CONTENTS:
  65.334 --			name = tcpa_pc_event_id_strings[event_id];
  65.335 -+			name = tcpa_pc_event_id_strings[pc_event->event_id];
  65.336 - 			n_len = strlen(name);
  65.337 - 			break;
  65.338 -+		/* hash data */
  65.339 - 		case POST_BIOS_ROM:
  65.340 - 		case ESCD:
  65.341 --			name = tcpa_pc_event_id_strings[event_id];
  65.342 -+		case OPTION_ROM_MICROCODE:
  65.343 -+		case S_CRTM_CONTENTS:
  65.344 -+		case POST_CONTENTS:
  65.345 -+			name = tcpa_pc_event_id_strings[pc_event->event_id];
  65.346 - 			n_len = strlen(name);
  65.347 - 			for (i = 0; i < 20; i++)
  65.348 --				d_len += sprintf(data, "%02x",
  65.349 --						event_entry[8 + i]);
  65.350 -+				d_len += sprintf(&data[2*i], "%02x",
  65.351 -+						pc_event->event_data[i]);
  65.352 - 			break;
  65.353 - 		default:
  65.354 - 			break;
  65.355 -@@ -260,52 +284,13 @@ static int get_event_name(char *dest, st
  65.356 - 
  65.357 - static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v)
  65.358 - {
  65.359 -+	struct tcpa_event *event = v;
  65.360 -+	char *data = v;
  65.361 -+	int i;
  65.362 - 
  65.363 --	char *eventname;
  65.364 --	char data[4];
  65.365 --	u32 help;
  65.366 --	int i, len;
  65.367 --	struct tcpa_event *event = (struct tcpa_event *) v;
  65.368 --	unsigned char *event_entry =
  65.369 --	    (unsigned char *) (v + sizeof(struct tcpa_event));
  65.370 --
  65.371 --	eventname = kmalloc(MAX_TEXT_EVENT, GFP_KERNEL);
  65.372 --	if (!eventname) {
  65.373 --		printk(KERN_ERR "%s: ERROR - No Memory for event name\n ",
  65.374 --		       __func__);
  65.375 --		return -ENOMEM;
  65.376 --	}
  65.377 --
  65.378 --	/* 1st: PCR used is in little-endian format (4 bytes) */
  65.379 --	help = le32_to_cpu(event->pcr_index);
  65.380 --	memcpy(data, &help, 4);
  65.381 --	for (i = 0; i < 4; i++)
  65.382 --		seq_putc(m, data[i]);
  65.383 --
  65.384 --	/* 2nd: SHA1 (20 bytes) */
  65.385 --	for (i = 0; i < 20; i++)
  65.386 --		seq_putc(m, event->pcr_value[i]);
  65.387 --
  65.388 --	/* 3rd: event type identifier (4 bytes) */
  65.389 --	help = le32_to_cpu(event->event_type);
  65.390 --	memcpy(data, &help, 4);
  65.391 --	for (i = 0; i < 4; i++)
  65.392 -+	for (i = 0; i < sizeof(struct tcpa_event) + event->event_size; i++)
  65.393 - 		seq_putc(m, data[i]);
  65.394 - 
  65.395 --	len = 0;
  65.396 --
  65.397 --	len += get_event_name(eventname, event, event_entry);
  65.398 --
  65.399 --	/* 4th:  filename <= 255 + \'0' delimiter */
  65.400 --	if (len > TCG_EVENT_NAME_LEN_MAX)
  65.401 --		len = TCG_EVENT_NAME_LEN_MAX;
  65.402 --
  65.403 --	for (i = 0; i < len; i++)
  65.404 --		seq_putc(m, eventname[i]);
  65.405 --
  65.406 --	/* 5th: delimiter */
  65.407 --	seq_putc(m, '\0');
  65.408 --
  65.409 - 	return 0;
  65.410 - }
  65.411 - 
  65.412 -@@ -353,6 +338,7 @@ static int tpm_ascii_bios_measurements_s
  65.413 - 	/* 4th: eventname <= max + \'0' delimiter */
  65.414 - 	seq_printf(m, " %s\n", eventname);
  65.415 - 
  65.416 -+	kfree(eventname);
  65.417 - 	return 0;
  65.418 - }
  65.419 - 
  65.420 -@@ -376,6 +362,7 @@ static int read_log(struct tpm_bios_log 
  65.421 - 	struct acpi_tcpa *buff;
  65.422 - 	acpi_status status;
  65.423 - 	struct acpi_table_header *virt;
  65.424 -+	u64 len, start;
  65.425 - 
  65.426 - 	if (log->bios_event_log != NULL) {
  65.427 - 		printk(KERN_ERR
  65.428 -@@ -396,27 +383,37 @@ static int read_log(struct tpm_bios_log 
  65.429 - 		return -EIO;
  65.430 - 	}
  65.431 - 
  65.432 --	if (buff->log_max_len == 0) {
  65.433 -+	switch(buff->platform_class) {
  65.434 -+	case BIOS_SERVER:
  65.435 -+		len = buff->server.log_max_len;
  65.436 -+		start = buff->server.log_start_addr;
  65.437 -+		break;
  65.438 -+	case BIOS_CLIENT:
  65.439 -+	default:
  65.440 -+		len = buff->client.log_max_len;
  65.441 -+		start = buff->client.log_start_addr;
  65.442 -+		break;
  65.443 -+	}
  65.444 -+	if (!len) {
  65.445 - 		printk(KERN_ERR "%s: ERROR - TCPA log area empty\n", __func__);
  65.446 - 		return -EIO;
  65.447 - 	}
  65.448 - 
  65.449 - 	/* malloc EventLog space */
  65.450 --	log->bios_event_log = kmalloc(buff->log_max_len, GFP_KERNEL);
  65.451 -+	log->bios_event_log = kmalloc(len, GFP_KERNEL);
  65.452 - 	if (!log->bios_event_log) {
  65.453 --		printk
  65.454 --		    ("%s: ERROR - Not enough  Memory for BIOS measurements\n",
  65.455 --		     __func__);
  65.456 -+		printk("%s: ERROR - Not enough  Memory for BIOS measurements\n",
  65.457 -+			__func__);
  65.458 - 		return -ENOMEM;
  65.459 - 	}
  65.460 - 
  65.461 --	log->bios_event_log_end = log->bios_event_log + buff->log_max_len;
  65.462 -+	log->bios_event_log_end = log->bios_event_log + len;
  65.463 - 
  65.464 --	acpi_os_map_memory(buff->log_start_addr, buff->log_max_len, (void *) &virt);
  65.465 -+	acpi_os_map_memory(start, len, (void *) &virt);
  65.466 - 
  65.467 --	memcpy(log->bios_event_log, virt, buff->log_max_len);
  65.468 -+	memcpy(log->bios_event_log, virt, len);
  65.469 - 
  65.470 --	acpi_os_unmap_memory(virt, buff->log_max_len);
  65.471 -+	acpi_os_unmap_memory(virt, len);
  65.472 - 	return 0;
  65.473 - }
  65.474 - 
  65.475 -diff -pruN ../orig-linux-2.6.16.29/drivers/char/tpm/tpm_infineon.c ./drivers/char/tpm/tpm_infineon.c
  65.476 ---- ../orig-linux-2.6.16.29/drivers/char/tpm/tpm_infineon.c	2006-09-12 19:02:10.000000000 +0100
  65.477 -+++ ./drivers/char/tpm/tpm_infineon.c	2006-09-19 14:05:52.000000000 +0100
  65.478 -@@ -15,6 +15,7 @@
  65.479 -  * License.
  65.480 -  */
  65.481 - 
  65.482 -+#include <linux/init.h>
  65.483 - #include <linux/pnp.h>
  65.484 - #include "tpm.h"
  65.485 - 
  65.486 -@@ -104,7 +105,7 @@ static int empty_fifo(struct tpm_chip *c
  65.487 - 
  65.488 - 	if (clear_wrfifo) {
  65.489 - 		for (i = 0; i < 4096; i++) {
  65.490 --			status = inb(chip->vendor->base + WRFIFO);
  65.491 -+			status = inb(chip->vendor.base + WRFIFO);
  65.492 - 			if (status == 0xff) {
  65.493 - 				if (check == 5)
  65.494 - 					break;
  65.495 -@@ -124,8 +125,8 @@ static int empty_fifo(struct tpm_chip *c
  65.496 - 	 */
  65.497 - 	i = 0;
  65.498 - 	do {
  65.499 --		status = inb(chip->vendor->base + RDFIFO);
  65.500 --		status = inb(chip->vendor->base + STAT);
  65.501 -+		status = inb(chip->vendor.base + RDFIFO);
  65.502 -+		status = inb(chip->vendor.base + STAT);
  65.503 - 		i++;
  65.504 - 		if (i == TPM_MAX_TRIES)
  65.505 - 			return -EIO;
  65.506 -@@ -138,7 +139,7 @@ static int wait(struct tpm_chip *chip, i
  65.507 - 	int status;
  65.508 - 	int i;
  65.509 - 	for (i = 0; i < TPM_MAX_TRIES; i++) {
  65.510 --		status = inb(chip->vendor->base + STAT);
  65.511 -+		status = inb(chip->vendor.base + STAT);
  65.512 - 		/* check the status-register if wait_for_bit is set */
  65.513 - 		if (status & 1 << wait_for_bit)
  65.514 - 			break;
  65.515 -@@ -157,7 +158,7 @@ static int wait(struct tpm_chip *chip, i
  65.516 - static void wait_and_send(struct tpm_chip *chip, u8 sendbyte)
  65.517 - {
  65.518 - 	wait(chip, STAT_XFE);
  65.519 --	outb(sendbyte, chip->vendor->base + WRFIFO);
  65.520 -+	outb(sendbyte, chip->vendor.base + WRFIFO);
  65.521 - }
  65.522 - 
  65.523 -     /* Note: WTX means Waiting-Time-Extension. Whenever the TPM needs more
  65.524 -@@ -204,7 +205,7 @@ recv_begin:
  65.525 - 		ret = wait(chip, STAT_RDA);
  65.526 - 		if (ret)
  65.527 - 			return -EIO;
  65.528 --		buf[i] = inb(chip->vendor->base + RDFIFO);
  65.529 -+		buf[i] = inb(chip->vendor.base + RDFIFO);
  65.530 - 	}
  65.531 - 
  65.532 - 	if (buf[0] != TPM_VL_VER) {
  65.533 -@@ -219,7 +220,7 @@ recv_begin:
  65.534 - 
  65.535 - 		for (i = 0; i < size; i++) {
  65.536 - 			wait(chip, STAT_RDA);
  65.537 --			buf[i] = inb(chip->vendor->base + RDFIFO);
  65.538 -+			buf[i] = inb(chip->vendor.base + RDFIFO);
  65.539 - 		}
  65.540 - 
  65.541 - 		if ((size == 0x6D00) && (buf[1] == 0x80)) {
  65.542 -@@ -268,7 +269,7 @@ static int tpm_inf_send(struct tpm_chip 
  65.543 - 	u8 count_high, count_low, count_4, count_3, count_2, count_1;
  65.544 - 
  65.545 - 	/* Disabling Reset, LP and IRQC */
  65.546 --	outb(RESET_LP_IRQC_DISABLE, chip->vendor->base + CMD);
  65.547 -+	outb(RESET_LP_IRQC_DISABLE, chip->vendor.base + CMD);
  65.548 - 
  65.549 - 	ret = empty_fifo(chip, 1);
  65.550 - 	if (ret) {
  65.551 -@@ -319,7 +320,7 @@ static void tpm_inf_cancel(struct tpm_ch
  65.552 - 
  65.553 - static u8 tpm_inf_status(struct tpm_chip *chip)
  65.554 - {
  65.555 --	return inb(chip->vendor->base + STAT);
  65.556 -+	return inb(chip->vendor.base + STAT);
  65.557 - }
  65.558 - 
  65.559 - static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
  65.560 -@@ -346,7 +347,7 @@ static struct file_operations inf_ops = 
  65.561 - 	.release = tpm_release,
  65.562 - };
  65.563 - 
  65.564 --static struct tpm_vendor_specific tpm_inf = {
  65.565 -+static const struct tpm_vendor_specific tpm_inf = {
  65.566 - 	.recv = tpm_inf_recv,
  65.567 - 	.send = tpm_inf_send,
  65.568 - 	.cancel = tpm_inf_cancel,
  65.569 -@@ -375,6 +376,7 @@ static int __devinit tpm_inf_pnp_probe(s
  65.570 - 	int version[2];
  65.571 - 	int productid[2];
  65.572 - 	char chipname[20];
  65.573 -+	struct tpm_chip *chip;
  65.574 - 
  65.575 - 	/* read IO-ports through PnP */
  65.576 - 	if (pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) &&
  65.577 -@@ -395,14 +397,13 @@ static int __devinit tpm_inf_pnp_probe(s
  65.578 - 			goto err_last;
  65.579 - 		}
  65.580 - 		/* publish my base address and request region */
  65.581 --		tpm_inf.base = TPM_INF_BASE;
  65.582 - 		if (request_region
  65.583 --		    (tpm_inf.base, TPM_INF_PORT_LEN, "tpm_infineon0") == NULL) {
  65.584 -+		    (TPM_INF_BASE, TPM_INF_PORT_LEN, "tpm_infineon0") == NULL) {
  65.585 - 			rc = -EINVAL;
  65.586 - 			goto err_last;
  65.587 - 		}
  65.588 --		if (request_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN,
  65.589 --				"tpm_infineon0") == NULL) {
  65.590 -+		if (request_region
  65.591 -+		    (TPM_INF_ADDR, TPM_INF_ADDR_LEN, "tpm_infineon0") == NULL) {
  65.592 - 			rc = -EINVAL;
  65.593 - 			goto err_last;
  65.594 - 		}
  65.595 -@@ -442,9 +443,9 @@ static int __devinit tpm_inf_pnp_probe(s
  65.596 - 
  65.597 - 		/* configure TPM with IO-ports */
  65.598 - 		outb(IOLIMH, TPM_INF_ADDR);
  65.599 --		outb(((tpm_inf.base >> 8) & 0xff), TPM_INF_DATA);
  65.600 -+		outb(((TPM_INF_BASE >> 8) & 0xff), TPM_INF_DATA);
  65.601 - 		outb(IOLIML, TPM_INF_ADDR);
  65.602 --		outb((tpm_inf.base & 0xff), TPM_INF_DATA);
  65.603 -+		outb((TPM_INF_BASE & 0xff), TPM_INF_DATA);
  65.604 - 
  65.605 - 		/* control if IO-ports are set correctly */
  65.606 - 		outb(IOLIMH, TPM_INF_ADDR);
  65.607 -@@ -452,10 +453,10 @@ static int __devinit tpm_inf_pnp_probe(s
  65.608 - 		outb(IOLIML, TPM_INF_ADDR);
  65.609 - 		iol = inb(TPM_INF_DATA);
  65.610 - 
  65.611 --		if ((ioh << 8 | iol) != tpm_inf.base) {
  65.612 -+		if ((ioh << 8 | iol) != TPM_INF_BASE) {
  65.613 - 			dev_err(&dev->dev,
  65.614 --				"Could not set IO-ports to 0x%lx\n",
  65.615 --				tpm_inf.base);
  65.616 -+				"Could not set IO-ports to 0x%x\n",
  65.617 -+				TPM_INF_BASE);
  65.618 - 			rc = -EIO;
  65.619 - 			goto err_release_region;
  65.620 - 		}
  65.621 -@@ -466,15 +467,15 @@ static int __devinit tpm_inf_pnp_probe(s
  65.622 - 		outb(DISABLE_REGISTER_PAIR, TPM_INF_ADDR);
  65.623 - 
  65.624 - 		/* disable RESET, LP and IRQC */
  65.625 --		outb(RESET_LP_IRQC_DISABLE, tpm_inf.base + CMD);
  65.626 -+		outb(RESET_LP_IRQC_DISABLE, TPM_INF_BASE + CMD);
  65.627 - 
  65.628 - 		/* Finally, we're done, print some infos */
  65.629 - 		dev_info(&dev->dev, "TPM found: "
  65.630 - 			 "config base 0x%x, "
  65.631 - 			 "io base 0x%x, "
  65.632 --			 "chip version %02x%02x, "
  65.633 --			 "vendor id %x%x (Infineon), "
  65.634 --			 "product id %02x%02x"
  65.635 -+			 "chip version 0x%02x%02x, "
  65.636 -+			 "vendor id 0x%x%x (Infineon), "
  65.637 -+			 "product id 0x%02x%02x"
  65.638 - 			 "%s\n",
  65.639 - 			 TPM_INF_ADDR,
  65.640 - 			 TPM_INF_BASE,
  65.641 -@@ -482,11 +483,10 @@ static int __devinit tpm_inf_pnp_probe(s
  65.642 - 			 vendorid[0], vendorid[1],
  65.643 - 			 productid[0], productid[1], chipname);
  65.644 - 
  65.645 --		rc = tpm_register_hardware(&dev->dev, &tpm_inf);
  65.646 --		if (rc < 0) {
  65.647 --			rc = -ENODEV;
  65.648 -+		if (!(chip = tpm_register_hardware(&dev->dev, &tpm_inf))) {
  65.649 - 			goto err_release_region;
  65.650 - 		}
  65.651 -+		chip->vendor.base = TPM_INF_BASE;
  65.652 - 		return 0;
  65.653 - 	} else {
  65.654 - 		rc = -ENODEV;
  65.655 -@@ -494,7 +494,7 @@ static int __devinit tpm_inf_pnp_probe(s
  65.656 - 	}
  65.657 - 
  65.658 - err_release_region:
  65.659 --	release_region(tpm_inf.base, TPM_INF_PORT_LEN);
  65.660 -+	release_region(TPM_INF_BASE, TPM_INF_PORT_LEN);
  65.661 - 	release_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN);
  65.662 - 
  65.663 - err_last:
  65.664 -@@ -506,7 +506,8 @@ static __devexit void tpm_inf_pnp_remove
  65.665 - 	struct tpm_chip *chip = pnp_get_drvdata(dev);
  65.666 - 
  65.667 - 	if (chip) {
  65.668 --		release_region(chip->vendor->base, TPM_INF_PORT_LEN);
  65.669 -+		release_region(TPM_INF_BASE, TPM_INF_PORT_LEN);
  65.670 -+		release_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN);
  65.671 - 		tpm_remove_hardware(chip->dev);
  65.672 - 	}
  65.673 - }
  65.674 -@@ -520,7 +521,7 @@ static struct pnp_driver tpm_inf_pnp = {
  65.675 - 	},
  65.676 - 	.id_table = tpm_pnp_tbl,
  65.677 - 	.probe = tpm_inf_pnp_probe,
  65.678 --	.remove = tpm_inf_pnp_remove,
  65.679 -+	.remove = __devexit_p(tpm_inf_pnp_remove),
  65.680 - };
  65.681 - 
  65.682 - static int __init init_inf(void)
  65.683 -@@ -538,5 +539,5 @@ module_exit(cleanup_inf);
  65.684 - 
  65.685 - MODULE_AUTHOR("Marcel Selhorst <selhorst@crypto.rub.de>");
  65.686 - MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2");
  65.687 --MODULE_VERSION("1.7");
  65.688 -+MODULE_VERSION("1.8");
  65.689 - MODULE_LICENSE("GPL");
  65.690 -diff -pruN ../orig-linux-2.6.16.29/drivers/char/tpm/tpm_nsc.c ./drivers/char/tpm/tpm_nsc.c
  65.691 ---- ../orig-linux-2.6.16.29/drivers/char/tpm/tpm_nsc.c	2006-09-12 19:02:10.000000000 +0100
  65.692 -+++ ./drivers/char/tpm/tpm_nsc.c	2006-09-19 14:05:52.000000000 +0100
  65.693 -@@ -71,7 +71,7 @@ static int wait_for_stat(struct tpm_chip
  65.694 - 	unsigned long stop;
  65.695 - 
  65.696 - 	/* status immediately available check */
  65.697 --	*data = inb(chip->vendor->base + NSC_STATUS);
  65.698 -+	*data = inb(chip->vendor.base + NSC_STATUS);
  65.699 - 	if ((*data & mask) == val)
  65.700 - 		return 0;
  65.701 - 
  65.702 -@@ -79,7 +79,7 @@ static int wait_for_stat(struct tpm_chip
  65.703 - 	stop = jiffies + 10 * HZ;
  65.704 - 	do {
  65.705 - 		msleep(TPM_TIMEOUT);
  65.706 --		*data = inb(chip->vendor->base + 1);
  65.707 -+		*data = inb(chip->vendor.base + 1);
  65.708 - 		if ((*data & mask) == val)
  65.709 - 			return 0;
  65.710 - 	}
  65.711 -@@ -94,9 +94,9 @@ static int nsc_wait_for_ready(struct tpm
  65.712 - 	unsigned long stop;
  65.713 - 
  65.714 - 	/* status immediately available check */
  65.715 --	status = inb(chip->vendor->base + NSC_STATUS);
  65.716 -+	status = inb(chip->vendor.base + NSC_STATUS);
  65.717 - 	if (status & NSC_STATUS_OBF)
  65.718 --		status = inb(chip->vendor->base + NSC_DATA);
  65.719 -+		status = inb(chip->vendor.base + NSC_DATA);
  65.720 - 	if (status & NSC_STATUS_RDY)
  65.721 - 		return 0;
  65.722 - 
  65.723 -@@ -104,9 +104,9 @@ static int nsc_wait_for_ready(struct tpm
  65.724 - 	stop = jiffies + 100;
  65.725 - 	do {
  65.726 - 		msleep(TPM_TIMEOUT);
  65.727 --		status = inb(chip->vendor->base + NSC_STATUS);
  65.728 -+		status = inb(chip->vendor.base + NSC_STATUS);
  65.729 - 		if (status & NSC_STATUS_OBF)
  65.730 --			status = inb(chip->vendor->base + NSC_DATA);
  65.731 -+			status = inb(chip->vendor.base + NSC_DATA);
  65.732 - 		if (status & NSC_STATUS_RDY)
  65.733 - 			return 0;
  65.734 - 	}
  65.735 -@@ -132,7 +132,7 @@ static int tpm_nsc_recv(struct tpm_chip 
  65.736 - 		return -EIO;
  65.737 - 	}
  65.738 - 	if ((data =
  65.739 --	     inb(chip->vendor->base + NSC_DATA)) != NSC_COMMAND_NORMAL) {
  65.740 -+	     inb(chip->vendor.base + NSC_DATA)) != NSC_COMMAND_NORMAL) {
  65.741 - 		dev_err(chip->dev, "not in normal mode (0x%x)\n",
  65.742 - 			data);
  65.743 - 		return -EIO;
  65.744 -@@ -148,7 +148,7 @@ static int tpm_nsc_recv(struct tpm_chip 
  65.745 - 		}
  65.746 - 		if (data & NSC_STATUS_F0)
  65.747 - 			break;
  65.748 --		*p = inb(chip->vendor->base + NSC_DATA);
  65.749 -+		*p = inb(chip->vendor.base + NSC_DATA);
  65.750 - 	}
  65.751 - 
  65.752 - 	if ((data & NSC_STATUS_F0) == 0 &&
  65.753 -@@ -156,7 +156,7 @@ static int tpm_nsc_recv(struct tpm_chip 
  65.754 - 		dev_err(chip->dev, "F0 not set\n");
  65.755 - 		return -EIO;
  65.756 - 	}
  65.757 --	if ((data = inb(chip->vendor->base + NSC_DATA)) != NSC_COMMAND_EOC) {
  65.758 -+	if ((data = inb(chip->vendor.base + NSC_DATA)) != NSC_COMMAND_EOC) {
  65.759 - 		dev_err(chip->dev,
  65.760 - 			"expected end of command(0x%x)\n", data);
  65.761 - 		return -EIO;
  65.762 -@@ -182,7 +182,7 @@ static int tpm_nsc_send(struct tpm_chip 
  65.763 - 	 * fix it. Not sure why this is needed, we followed the flow
  65.764 - 	 * chart in the manual to the letter.
  65.765 - 	 */
  65.766 --	outb(NSC_COMMAND_CANCEL, chip->vendor->base + NSC_COMMAND);
  65.767 -+	outb(NSC_COMMAND_CANCEL, chip->vendor.base + NSC_COMMAND);
  65.768 - 
  65.769 - 	if (nsc_wait_for_ready(chip) != 0)
  65.770 - 		return -EIO;
  65.771 -@@ -192,7 +192,7 @@ static int tpm_nsc_send(struct tpm_chip 
  65.772 - 		return -EIO;
  65.773 - 	}
  65.774 - 
  65.775 --	outb(NSC_COMMAND_NORMAL, chip->vendor->base + NSC_COMMAND);
  65.776 -+	outb(NSC_COMMAND_NORMAL, chip->vendor.base + NSC_COMMAND);
  65.777 - 	if (wait_for_stat(chip, NSC_STATUS_IBR, NSC_STATUS_IBR, &data) < 0) {
  65.778 - 		dev_err(chip->dev, "IBR timeout\n");
  65.779 - 		return -EIO;
  65.780 -@@ -204,26 +204,26 @@ static int tpm_nsc_send(struct tpm_chip 
  65.781 - 				"IBF timeout (while writing data)\n");
  65.782 - 			return -EIO;
  65.783 - 		}
  65.784 --		outb(buf[i], chip->vendor->base + NSC_DATA);
  65.785 -+		outb(buf[i], chip->vendor.base + NSC_DATA);
  65.786 - 	}
  65.787 - 
  65.788 - 	if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) {
  65.789 - 		dev_err(chip->dev, "IBF timeout\n");
  65.790 - 		return -EIO;
  65.791 - 	}
  65.792 --	outb(NSC_COMMAND_EOC, chip->vendor->base + NSC_COMMAND);
  65.793 -+	outb(NSC_COMMAND_EOC, chip->vendor.base + NSC_COMMAND);
  65.794 - 
  65.795 - 	return count;
  65.796 - }
  65.797 - 
  65.798 - static void tpm_nsc_cancel(struct tpm_chip *chip)
  65.799 - {
  65.800 --	outb(NSC_COMMAND_CANCEL, chip->vendor->base + NSC_COMMAND);
  65.801 -+	outb(NSC_COMMAND_CANCEL, chip->vendor.base + NSC_COMMAND);
  65.802 - }
  65.803 - 
  65.804 - static u8 tpm_nsc_status(struct tpm_chip *chip)
  65.805 - {
  65.806 --	return inb(chip->vendor->base + NSC_STATUS);
  65.807 -+	return inb(chip->vendor.base + NSC_STATUS);
  65.808 - }
  65.809 - 
  65.810 - static struct file_operations nsc_ops = {
  65.811 -@@ -250,7 +250,7 @@ static struct attribute * nsc_attrs[] = 
  65.812 - 
  65.813 - static struct attribute_group nsc_attr_grp = { .attrs = nsc_attrs };
  65.814 - 
  65.815 --static struct tpm_vendor_specific tpm_nsc = {
  65.816 -+static const struct tpm_vendor_specific tpm_nsc = {
  65.817 - 	.recv = tpm_nsc_recv,
  65.818 - 	.send = tpm_nsc_send,
  65.819 - 	.cancel = tpm_nsc_cancel,
  65.820 -@@ -268,7 +268,7 @@ static void __devexit tpm_nsc_remove(str
  65.821 - {
  65.822 - 	struct tpm_chip *chip = dev_get_drvdata(dev);
  65.823 - 	if ( chip ) {
  65.824 --		release_region(chip->vendor->base, 2);
  65.825 -+		release_region(chip->vendor.base, 2);
  65.826 - 		tpm_remove_hardware(chip->dev);
  65.827 - 	}
  65.828 - }
  65.829 -@@ -286,7 +286,8 @@ static int __init init_nsc(void)
  65.830 - 	int rc = 0;
  65.831 - 	int lo, hi;
  65.832 - 	int nscAddrBase = TPM_ADDR;
  65.833 --
  65.834 -+	struct tpm_chip *chip;
  65.835 -+	unsigned long base;
  65.836 - 
  65.837 - 	/* verify that it is a National part (SID) */
  65.838 - 	if (tpm_read_index(TPM_ADDR, NSC_SID_INDEX) != 0xEF) {
  65.839 -@@ -300,7 +301,7 @@ static int __init init_nsc(void)
  65.840 - 
  65.841 - 	hi = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_HI);
  65.842 - 	lo = tpm_read_index(nscAddrBas