commit 82649ddef6a1190fc449d739f74699c3a2753082 Author: Rosa Date: Sat Apr 14 04:10:33 2012 +0400 Automatic import for version 2.6.32.11 diff --git a/.abf.yml b/.abf.yml new file mode 100644 index 0000000..01cebb8 --- /dev/null +++ b/.abf.yml @@ -0,0 +1,2 @@ +sources: + "linux-2.6.32.11.tar.bz2": 67b40af11576077ac0443b24483b66e123ea542b diff --git a/SoN-23-mm-swapfile.patch b/SoN-23-mm-swapfile.patch new file mode 100644 index 0000000..53756ef --- /dev/null +++ b/SoN-23-mm-swapfile.patch @@ -0,0 +1,363 @@ +From: Peter Zijlstra +Subject: [PATCH 23/31] mm: add support for non block device backed swap files + +New addres_space_operations methods are added: + int swapon(struct file *); + int swapoff(struct file *); + int swap_out(struct file *, struct page *, struct writeback_control *); + int swap_in(struct file *, struct page *); + +When during sys_swapon() the ->swapon() method is found and returns no error +the swapper_space.a_ops will proxy to sis->swap_file->f_mapping->a_ops, and +make use of ->swap_{out,in}() to write/read swapcache pages. + +The ->swapon() method will be used to communicate to the file that the VM +relies on it, and the address_space should take adequate measures (like +reserving memory for mempools or the like). The ->swapoff() method will be +called on sys_swapoff() when ->swapon() was found and returned no error. + +This new interface can be used to obviate the need for ->bmap in the swapfile +code. A filesystem would need to load (and maybe even allocate) the full block +map for a file into memory and pin it there on ->swapon() so that +->swap_{out,in}() have instant access to it. It can be released on ->swapoff(). + +The reason to provide ->swap_{out,in}() over using {write,read}page() is to + 1) make a distinction between swapcache and pagecache pages, and + 2) to provide a struct file * for credential context (normally not needed + in the context of writepage, as the page content is normally dirtied + using either of the following interfaces: + write_{begin,end}() + {prepare,commit}_write() + page_mkwrite() + which do have the file context. + +[miklos@szeredi.hu: cleanups] +Signed-off-by: Peter Zijlstra +Signed-off-by: Suresh Jayaraman +--- + Documentation/filesystems/Locking | 22 ++++++++++++++++ + Documentation/filesystems/vfs.txt | 18 +++++++++++++ + include/linux/buffer_head.h | 1 + include/linux/fs.h | 9 ++++++ + include/linux/swap.h | 4 ++ + mm/page_io.c | 52 ++++++++++++++++++++++++++++++++++++++ + mm/swap_state.c | 4 +- + mm/swapfile.c | 30 ++++++++++++++++++++- + 8 files changed, 136 insertions(+), 4 deletions(-) + +Index: linux-2.6.32-master/Documentation/filesystems/Locking +=================================================================== +--- linux-2.6.32-master.orig/Documentation/filesystems/Locking ++++ linux-2.6.32-master/Documentation/filesystems/Locking +@@ -174,6 +174,10 @@ prototypes: + int (*direct_IO)(int, struct kiocb *, const struct iovec *iov, + loff_t offset, unsigned long nr_segs); + int (*launder_page) (struct page *); ++ int (*swapon) (struct file *); ++ int (*swapoff) (struct file *); ++ int (*swap_out) (struct file *, struct page *, struct writeback_control *); ++ int (*swap_in) (struct file *, struct page *); + + locking rules: + All except set_page_dirty may block +@@ -193,6 +197,10 @@ invalidatepage: no yes + releasepage: no yes + direct_IO: no + launder_page: no yes ++swapon no ++swapoff no ++swap_out no yes, unlocks ++swap_in no yes, unlocks + + ->write_begin(), ->write_end(), ->sync_page() and ->readpage() + may be called from the request handler (/dev/loop). +@@ -292,6 +300,20 @@ cleaned, or an error value if not. Note + getting mapped back in and redirtied, it needs to be kept locked + across the entire operation. + ++ ->swapon() will be called with a non-zero argument on files backing ++(non block device backed) swapfiles. A return value of zero indicates success, ++in which case this file can be used for backing swapspace. The swapspace ++operations will be proxied to the address space operations. ++ ++ ->swapoff() will be called in the sys_swapoff() path when ->swapon() ++returned success. ++ ++ ->swap_out() when swapon() returned success, this method is used to ++write the swap page. ++ ++ ->swap_in() when swapon() returned success, this method is used to ++read the swap page. ++ + Note: currently almost all instances of address_space methods are + using BKL for internal serialization and that's one of the worst sources + of contention. Normally they are calling library functions (in fs/buffer.c) +Index: linux-2.6.32-master/Documentation/filesystems/vfs.txt +=================================================================== +--- linux-2.6.32-master.orig/Documentation/filesystems/vfs.txt ++++ linux-2.6.32-master/Documentation/filesystems/vfs.txt +@@ -537,6 +537,11 @@ struct address_space_operations { + int (*migratepage) (struct page *, struct page *); + int (*launder_page) (struct page *); + int (*error_remove_page) (struct mapping *mapping, struct page *page); ++ int (*swapon)(struct file *); ++ int (*swapoff)(struct file *); ++ int (*swap_out)(struct file *file, struct page *page, ++ struct writeback_control *wbc); ++ int (*swap_in)(struct file *file, struct page *page); + }; + + writepage: called by the VM to write a dirty page to backing store. +@@ -701,6 +706,19 @@ struct address_space_operations { + unless you have them locked or reference counts increased. + + ++ swapon: Called when swapon is used on a file. A ++ return value of zero indicates success, in which case this ++ file can be used to back swapspace. The swapspace operations ++ will be proxied to this address space's ->swap_{out,in} methods. ++ ++ swapoff: Called during swapoff on files where swapon was successfull. ++ ++ swap_out: Called to write a swapcache page to a backing store, similar to ++ writepage. ++ ++ swap_in: Called to read a swapcache page from a backing store, similar to ++ readpage. ++ + The File Object + =============== + +Index: linux-2.6.32-master/include/linux/buffer_head.h +=================================================================== +--- linux-2.6.32-master.orig/include/linux/buffer_head.h ++++ linux-2.6.32-master/include/linux/buffer_head.h +@@ -339,6 +339,7 @@ static inline int inode_has_buffers(stru + static inline void invalidate_inode_buffers(struct inode *inode) {} + static inline int remove_inode_buffers(struct inode *inode) { return 1; } + static inline int sync_mapping_buffers(struct address_space *mapping) { return 0; } ++static inline void block_sync_page(struct page *) { } + + #endif /* CONFIG_BLOCK */ + #endif /* _LINUX_BUFFER_HEAD_H */ +Index: linux-2.6.32-master/include/linux/fs.h +=================================================================== +--- linux-2.6.32-master.orig/include/linux/fs.h ++++ linux-2.6.32-master/include/linux/fs.h +@@ -603,6 +603,15 @@ struct address_space_operations { + int (*is_partially_uptodate) (struct page *, read_descriptor_t *, + unsigned long); + int (*error_remove_page)(struct address_space *, struct page *); ++ ++ /* ++ * swapfile support ++ */ ++ int (*swapon)(struct file *file); ++ int (*swapoff)(struct file *file); ++ int (*swap_out)(struct file *file, struct page *page, ++ struct writeback_control *wbc); ++ int (*swap_in)(struct file *file, struct page *page); + }; + + /* +Index: linux-2.6.32-master/include/linux/swap.h +=================================================================== +--- linux-2.6.32-master.orig/include/linux/swap.h ++++ linux-2.6.32-master/include/linux/swap.h +@@ -145,6 +145,7 @@ enum { + SWP_DISCARDABLE = (1 << 2), /* blkdev supports discard */ + SWP_DISCARDING = (1 << 3), /* now discarding a free cluster */ + SWP_SOLIDSTATE = (1 << 4), /* blkdev seeks are cheap */ ++ SWP_FILE = (1 << 5), /* file swap area */ + /* add others here before... */ + SWP_SCANNING = (1 << 8), /* refcount in scan_swap_map */ + }; +@@ -285,6 +286,8 @@ extern void swap_unplug_io_fn(struct bac + /* linux/mm/page_io.c */ + extern int swap_readpage(struct page *); + extern int swap_writepage(struct page *page, struct writeback_control *wbc); ++extern void swap_sync_page(struct page *page); ++extern int swap_set_page_dirty(struct page *page); + extern void end_swap_bio_read(struct bio *bio, int err); + + /* linux/mm/swap_state.c */ +@@ -320,6 +323,7 @@ extern unsigned int count_swap_pages(int + extern sector_t map_swap_page(struct swap_info_struct *, pgoff_t); + extern sector_t swapdev_block(int, pgoff_t); + extern struct swap_info_struct *get_swap_info_struct(unsigned); ++extern struct swap_info_struct *page_swap_info(struct page *); + extern int reuse_swap_page(struct page *); + extern int try_to_free_swap(struct page *); + struct backing_dev_info; +Index: linux-2.6.32-master/mm/page_io.c +=================================================================== +--- linux-2.6.32-master.orig/mm/page_io.c ++++ linux-2.6.32-master/mm/page_io.c +@@ -16,6 +16,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -97,11 +98,23 @@ int swap_writepage(struct page *page, st + { + struct bio *bio; + int ret = 0, rw = WRITE; ++ struct swap_info_struct *sis = page_swap_info(page); + + if (try_to_free_swap(page)) { + unlock_page(page); + goto out; + } ++ ++ if (sis->flags & SWP_FILE) { ++ struct file *swap_file = sis->swap_file; ++ struct address_space *mapping = swap_file->f_mapping; ++ ++ ret = mapping->a_ops->swap_out(swap_file, page, wbc); ++ if (!ret) ++ count_vm_event(PSWPOUT); ++ return ret; ++ } ++ + bio = get_swap_bio(GFP_NOIO, page_private(page), page, + end_swap_bio_write); + if (bio == NULL) { +@@ -120,13 +133,52 @@ out: + return ret; + } + ++void swap_sync_page(struct page *page) ++{ ++ struct swap_info_struct *sis = page_swap_info(page); ++ ++ if (sis->flags & SWP_FILE) { ++ struct address_space *mapping = sis->swap_file->f_mapping; ++ ++ if (mapping->a_ops->sync_page) ++ mapping->a_ops->sync_page(page); ++ } else { ++ block_sync_page(page); ++ } ++} ++ ++int swap_set_page_dirty(struct page *page) ++{ ++ struct swap_info_struct *sis = page_swap_info(page); ++ ++ if (sis->flags & SWP_FILE) { ++ struct address_space *mapping = sis->swap_file->f_mapping; ++ ++ return mapping->a_ops->set_page_dirty(page); ++ } else { ++ return __set_page_dirty_nobuffers(page); ++ } ++} ++ + int swap_readpage(struct page *page) + { + struct bio *bio; + int ret = 0; ++ struct swap_info_struct *sis = page_swap_info(page); + + VM_BUG_ON(!PageLocked(page)); + VM_BUG_ON(PageUptodate(page)); ++ ++ if (sis->flags & SWP_FILE) { ++ struct file *swap_file = sis->swap_file; ++ struct address_space *mapping = swap_file->f_mapping; ++ ++ ret = mapping->a_ops->swap_in(swap_file, page); ++ if (!ret) ++ count_vm_event(PSWPIN); ++ return ret; ++ } ++ + bio = get_swap_bio(GFP_KERNEL, page_private(page), page, + end_swap_bio_read); + if (bio == NULL) { +Index: linux-2.6.32-master/mm/swap_state.c +=================================================================== +--- linux-2.6.32-master.orig/mm/swap_state.c ++++ linux-2.6.32-master/mm/swap_state.c +@@ -28,8 +28,8 @@ + */ + static const struct address_space_operations swap_aops = { + .writepage = swap_writepage, +- .sync_page = block_sync_page, +- .set_page_dirty = __set_page_dirty_nobuffers, ++ .sync_page = swap_sync_page, ++ .set_page_dirty = swap_set_page_dirty, + .migratepage = migrate_page, + }; + +Index: linux-2.6.32-master/mm/swapfile.c +=================================================================== +--- linux-2.6.32-master.orig/mm/swapfile.c ++++ linux-2.6.32-master/mm/swapfile.c +@@ -1336,6 +1336,14 @@ static void destroy_swap_extents(struct + list_del(&se->list); + kfree(se); + } ++ ++ if (sis->flags & SWP_FILE) { ++ struct file *swap_file = sis->swap_file; ++ struct address_space *mapping = swap_file->f_mapping; ++ ++ sis->flags &= ~SWP_FILE; ++ mapping->a_ops->swapoff(swap_file); ++ } + } + + /* +@@ -1410,7 +1418,9 @@ add_swap_extent(struct swap_info_struct + */ + static int setup_swap_extents(struct swap_info_struct *sis, sector_t *span) + { +- struct inode *inode; ++ struct file *swap_file = sis->swap_file; ++ struct address_space *mapping = swap_file->f_mapping; ++ struct inode *inode = mapping->host; + unsigned blocks_per_page; + unsigned long page_no; + unsigned blkbits; +@@ -1421,13 +1431,22 @@ static int setup_swap_extents(struct swa + int nr_extents = 0; + int ret; + +- inode = sis->swap_file->f_mapping->host; + if (S_ISBLK(inode->i_mode)) { + ret = add_swap_extent(sis, 0, sis->max, 0); + *span = sis->pages; + goto done; + } + ++ if (mapping->a_ops->swapon) { ++ ret = mapping->a_ops->swapon(swap_file); ++ if (!ret) { ++ sis->flags |= SWP_FILE; ++ ret = add_swap_extent(sis, 0, sis->max, 0); ++ *span = sis->pages; ++ } ++ goto done; ++ } ++ + blkbits = inode->i_blkbits; + blocks_per_page = PAGE_SIZE >> blkbits; + +@@ -2166,6 +2185,13 @@ get_swap_info_struct(unsigned type) + return &swap_info[type]; + } + ++struct swap_info_struct *page_swap_info(struct page *page) ++{ ++ swp_entry_t swap = { .val = page_private(page) }; ++ BUG_ON(!PageSwapCache(page)); ++ return &swap_info[swp_type(swap)]; ++} ++ + /* + * swap_lock prevents swap_map being freed. Don't grab an extra + * reference on the swaphandle, it doesn't matter if it becomes unused. diff --git a/add-console-use-vt b/add-console-use-vt new file mode 100644 index 0000000..7610e99 --- /dev/null +++ b/add-console-use-vt @@ -0,0 +1,46 @@ +Subject: add console_use_vt +From: kraxel@suse.de +Patch-mainline: no + +$subject says all + +--- sle11sp1-2010-03-01.orig/drivers/char/tty_io.c 2010-03-01 14:09:07.000000000 +0100 ++++ sle11sp1-2010-03-01/drivers/char/tty_io.c 2010-03-01 14:09:43.000000000 +0100 +@@ -136,6 +136,8 @@ LIST_HEAD(tty_drivers); /* linked list + DEFINE_MUTEX(tty_mutex); + EXPORT_SYMBOL(tty_mutex); + ++int console_use_vt = 1; ++ + static ssize_t tty_read(struct file *, char __user *, size_t, loff_t *); + static ssize_t tty_write(struct file *, const char __user *, size_t, loff_t *); + ssize_t redirected_tty_write(struct file *, const char __user *, +@@ -1736,7 +1738,7 @@ retry_open: + goto got_driver; + } + #ifdef CONFIG_VT +- if (device == MKDEV(TTY_MAJOR, 0)) { ++ if (console_use_vt && device == MKDEV(TTY_MAJOR, 0)) { + extern struct tty_driver *console_driver; + driver = tty_driver_kref_get(console_driver); + index = fg_console; +@@ -3138,7 +3140,8 @@ static int __init tty_init(void) + "console"); + + #ifdef CONFIG_VT +- vty_init(&console_fops); ++ if (console_use_vt) ++ vty_init(&console_fops); + #endif + return 0; + } +--- sle11sp1-2010-03-01.orig/include/linux/console.h 2010-03-01 14:09:07.000000000 +0100 ++++ sle11sp1-2010-03-01/include/linux/console.h 2009-10-12 12:16:48.000000000 +0200 +@@ -63,6 +63,7 @@ extern const struct consw dummy_con; /* + extern const struct consw vga_con; /* VGA text console */ + extern const struct consw newport_con; /* SGI Newport console */ + extern const struct consw prom_con; /* SPARC PROM console */ ++extern int console_use_vt; + + int con_is_bound(const struct consw *csw); + int register_con_driver(const struct consw *csw, int first, int last); diff --git a/bug-561933_uv_pat_is_gru_range.patch b/bug-561933_uv_pat_is_gru_range.patch new file mode 100644 index 0000000..2bb874b --- /dev/null +++ b/bug-561933_uv_pat_is_gru_range.patch @@ -0,0 +1,166 @@ +From: Jack Steiner +Subject: x86: UV SGI: Don't track GRU space in PAT +References: bnc#561933, fate#306952 +Patch-mainline: 2.6.33-rc1 +Git-commit: fd12a0d69aee6d90fa9b9890db24368a897f8423 + +GRU space is always mapped as WB in the page table. There is +no need to track the mappings in the PAT. This also eliminates +the "freeing invalid memtype" messages when the GRU space is unmapped. + +Version 2 with changes suggested by Ingo (at least I think I understood what +he wanted). + +Version 3 with changes suggested by Peter to make the new function +a member of the x86_platform structure. + +Signed-off-by: Jack Steiner +Signed-off-by: Rafael J. Wysocki +--- + + arch/x86/include/asm/pat.h | 2 ++ + arch/x86/include/asm/x86_init.h | 2 ++ + arch/x86/kernel/apic/x2apic_uv_x.c | 19 ++++++++++++++++++- + arch/x86/kernel/x86_init.c | 2 ++ + arch/x86/mm/pat.c | 12 +++++++++--- + 5 files changed, 33 insertions(+), 4 deletions(-) + +--- a/arch/x86/include/asm/pat.h ++++ b/arch/x86/include/asm/pat.h +@@ -24,4 +24,6 @@ int io_reserve_memtype(resource_size_t s + + void io_free_memtype(resource_size_t start, resource_size_t end); + ++int default_is_untracked_pat_range(u64 start, u64 end); ++ + #endif /* _ASM_X86_PAT_H */ +--- a/arch/x86/include/asm/x86_init.h ++++ b/arch/x86/include/asm/x86_init.h +@@ -113,11 +113,13 @@ struct x86_cpuinit_ops { + + /** + * struct x86_platform_ops - platform specific runtime functions ++ * @is_untracked_pat_range exclude from PAT logic + * @calibrate_tsc: calibrate TSC + * @get_wallclock: get time from HW clock like RTC etc. + * @set_wallclock: set time back to HW clock + */ + struct x86_platform_ops { ++ int (*is_untracked_pat_range)(u64 start, u64 end); + unsigned long (*calibrate_tsc)(void); + unsigned long (*get_wallclock)(void); + int (*set_wallclock)(unsigned long nowtime); +--- a/arch/x86/kernel/apic/x2apic_uv_x.c ++++ b/arch/x86/kernel/apic/x2apic_uv_x.c +@@ -30,10 +30,22 @@ + #include + #include + #include ++#include + + DEFINE_PER_CPU(int, x2apic_extra_bits); + + static enum uv_system_type uv_system_type; ++static u64 gru_start_paddr, gru_end_paddr; ++ ++static int is_GRU_range(u64 start, u64 end) ++{ ++ return start >= gru_start_paddr && end < gru_end_paddr; ++} ++ ++static int uv_is_untracked_pat_range(u64 start, u64 end) ++{ ++ return is_ISA_range(start, end) || is_GRU_range(start, end); ++} + + static int early_get_nodeid(void) + { +@@ -49,6 +61,7 @@ static int early_get_nodeid(void) + static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id) + { + if (!strcmp(oem_id, "SGI")) { ++ x86_platform.is_untracked_pat_range = uv_is_untracked_pat_range; + if (!strcmp(oem_table_id, "UVL")) + uv_system_type = UV_LEGACY_APIC; + else if (!strcmp(oem_table_id, "UVX")) +@@ -385,8 +398,12 @@ static __init void map_gru_high(int max_ + int shift = UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_SHFT; + + gru.v = uv_read_local_mmr(UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR); +- if (gru.s.enable) ++ if (gru.s.enable) { + map_high("GRU", gru.s.base, shift, shift, max_pnode, map_wb); ++ gru_start_paddr = ((u64)gru.s.base << shift); ++ gru_end_paddr = gru_start_paddr + (1UL << shift) * (max_pnode + 1); ++ ++ } + } + + static __init void map_mmr_high(int max_pnode) +--- a/arch/x86/kernel/x86_init.c ++++ b/arch/x86/kernel/x86_init.c +@@ -13,6 +13,7 @@ + #include + #include + #include ++#include + #include + + void __cpuinit x86_init_noop(void) { } +@@ -69,6 +70,7 @@ struct x86_cpuinit_ops x86_cpuinit __cpu + }; + + struct x86_platform_ops x86_platform = { ++ .is_untracked_pat_range = default_is_untracked_pat_range, + .calibrate_tsc = native_calibrate_tsc, + .get_wallclock = mach_get_cmos_time, + .set_wallclock = mach_set_rtc_mmss, +--- a/arch/x86/mm/pat.c ++++ b/arch/x86/mm/pat.c +@@ -20,6 +20,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -348,6 +349,11 @@ static int free_ram_pages_type(u64 start + return 0; + } + ++int default_is_untracked_pat_range(u64 start, u64 end) ++{ ++ return is_ISA_range(start, end); ++} ++ + /* + * req_type typically has one of the: + * - _PAGE_CACHE_WB +@@ -388,7 +394,7 @@ int reserve_memtype(u64 start, u64 end, + } + + /* Low ISA region is always mapped WB in page table. No need to track */ +- if (is_ISA_range(start, end - 1)) { ++ if (x86_platform.is_untracked_pat_range(start, end - 1)) { + if (new_type) + *new_type = _PAGE_CACHE_WB; + return 0; +@@ -499,7 +505,7 @@ int free_memtype(u64 start, u64 end) + return 0; + + /* Low ISA region is always mapped WB. No need to track */ +- if (is_ISA_range(start, end - 1)) ++ if (x86_platform.is_untracked_pat_range(start, end - 1)) + return 0; + + is_range_ram = pat_pagerange_is_ram(start, end); +@@ -582,7 +588,7 @@ static unsigned long lookup_memtype(u64 + int rettype = _PAGE_CACHE_WB; + struct memtype *entry; + +- if (is_ISA_range(paddr, paddr + PAGE_SIZE - 1)) ++ if (x86_platform.is_untracked_pat_range(paddr, paddr + PAGE_SIZE - 1)) + return rettype; + + if (pat_pagerange_is_ram(paddr, paddr + PAGE_SIZE)) { diff --git a/disable-mrproper-in-devel-rpms.patch b/disable-mrproper-in-devel-rpms.patch new file mode 100644 index 0000000..0e35090 --- /dev/null +++ b/disable-mrproper-in-devel-rpms.patch @@ -0,0 +1,33 @@ +--- + Makefile | 12 ++++-------- + 1 file changed, 4 insertions(+), 8 deletions(-) + +diff -p -up linux-2.6.32/Makefile.orig linux-2.6.32/Makefile +--- linux-2.6.32/Makefile.orig 2009-12-10 18:24:46.341174801 -0200 ++++ linux-2.6.32/Makefile 2009-12-10 18:25:22.919299464 -0200 +@@ -1192,13 +1192,9 @@ CLEAN_DIRS += $(MODVERDIR) + CLEAN_FILES += vmlinux System.map \ + .tmp_kallsyms* .tmp_version .tmp_vmlinux* .tmp_System.map + +-# Directories & files removed with 'make mrproper' +-MRPROPER_DIRS += include/config include2 usr/include include/generated +-MRPROPER_FILES += .config .config.old include/asm .version .old_version \ +- include/linux/autoconf.h include/linux/version.h \ +- include/linux/utsrelease.h \ +- include/linux/bounds.h include/asm*/asm-offsets.h \ +- Module.symvers Module.markers tags TAGS cscope* ++# This is a -devel rpm, so we dont let mrproper remove anything /tmb 12.10.2007 ++MRPROPER_DIRS += "" ++MRPROPER_FILES += "" + + # clean - Delete most, but leave enough to build external modules + # +@@ -1224,7 +1220,7 @@ clean: archclean $(clean-dirs) + # + mrproper: rm-dirs := $(wildcard $(MRPROPER_DIRS)) + mrproper: rm-files := $(wildcard $(MRPROPER_FILES)) +-mrproper-dirs := $(addprefix _mrproper_,Documentation/DocBook scripts) ++mrproper-dirs := $(addprefix _mrproper_,Documentation/DocBook) + + PHONY += $(mrproper-dirs) mrproper archmrproper + $(mrproper-dirs): diff --git a/fix_clock_gettime_vsyscall_time_warp.diff b/fix_clock_gettime_vsyscall_time_warp.diff new file mode 100644 index 0000000..8e52a7a --- /dev/null +++ b/fix_clock_gettime_vsyscall_time_warp.diff @@ -0,0 +1,161 @@ +From: Lin Ming +Subject: timekeeping: Fix clock_gettime vsyscall time warp +Patch-mainline: 0696b711e4be45fa104c12329f617beb29c03f78 +References: bnc#569238 + +commit 0696b711e4be45fa104c12329f617beb29c03f78 +Author: Lin Ming +Date: Tue Nov 17 13:49:50 2009 +0800 + + timekeeping: Fix clock_gettime vsyscall time warp + + Since commit 0a544198 "timekeeping: Move NTP adjusted clock multiplier + to struct timekeeper" the clock multiplier of vsyscall is updated with + the unmodified clock multiplier of the clock source and not with the + NTP adjusted multiplier of the timekeeper. + + This causes user space observerable time warps: + new CLOCK-warp maximum: 120 nsecs, 00000025c337c537 -> 00000025c337c4bf + + Add a new argument "mult" to update_vsyscall() and hand in the + timekeeping internal NTP adjusted multiplier. + + Signed-off-by: Lin Ming + Cc: "Zhang Yanmin" + Cc: Martin Schwidefsky + Cc: Benjamin Herrenschmidt + Cc: Tony Luck + LKML-Reference: <1258436990.17765.83.camel@minggr.sh.intel.com> + Signed-off-by: Thomas Gleixner + +Signed-off-by: Kurt Garloff + +--- + arch/ia64/kernel/time.c | 4 ++-- + arch/powerpc/kernel/time.c | 5 +++-- + arch/s390/kernel/time.c | 3 ++- + arch/x86/kernel/vsyscall_64.c | 5 +++-- + include/linux/clocksource.h | 6 ++++-- + kernel/time/timekeeping.c | 6 +++--- + 6 files changed, 17 insertions(+), 12 deletions(-) + +--- a/arch/ia64/kernel/time.c ++++ b/arch/ia64/kernel/time.c +@@ -473,7 +473,7 @@ void update_vsyscall_tz(void) + { + } + +-void update_vsyscall(struct timespec *wall, struct clocksource *c) ++void update_vsyscall(struct timespec *wall, struct clocksource *c, u32 mult) + { + unsigned long flags; + +@@ -481,7 +481,7 @@ void update_vsyscall(struct timespec *wa + + /* copy fsyscall clock data */ + fsyscall_gtod_data.clk_mask = c->mask; +- fsyscall_gtod_data.clk_mult = c->mult; ++ fsyscall_gtod_data.clk_mult = mult; + fsyscall_gtod_data.clk_shift = c->shift; + fsyscall_gtod_data.clk_fsys_mmio = c->fsys_mmio; + fsyscall_gtod_data.clk_cycle_last = c->cycle_last; +--- a/arch/powerpc/kernel/time.c ++++ b/arch/powerpc/kernel/time.c +@@ -828,7 +828,8 @@ static cycle_t timebase_read(struct cloc + return (cycle_t)get_tb(); + } + +-void update_vsyscall(struct timespec *wall_time, struct clocksource *clock) ++void update_vsyscall(struct timespec *wall_time, struct clocksource *clock, ++ u32 mult) + { + u64 t2x, stamp_xsec; + +@@ -841,7 +842,7 @@ void update_vsyscall(struct timespec *wa + + /* XXX this assumes clock->shift == 22 */ + /* 4611686018 ~= 2^(20+64-22) / 1e9 */ +- t2x = (u64) clock->mult * 4611686018ULL; ++ t2x = (u64) mult * 4611686018ULL; + stamp_xsec = (u64) xtime.tv_nsec * XSEC_PER_SEC; + do_div(stamp_xsec, 1000000000); + stamp_xsec += (u64) xtime.tv_sec * XSEC_PER_SEC; +--- a/arch/s390/kernel/time.c ++++ b/arch/s390/kernel/time.c +@@ -214,7 +214,8 @@ struct clocksource * __init clocksource_ + return &clocksource_tod; + } + +-void update_vsyscall(struct timespec *wall_time, struct clocksource *clock) ++void update_vsyscall(struct timespec *wall_time, struct clocksource *clock, ++ u32 mult) + { + if (clock != &clocksource_tod) + return; +--- a/arch/x86/kernel/vsyscall_64.c ++++ b/arch/x86/kernel/vsyscall_64.c +@@ -73,7 +73,8 @@ void update_vsyscall_tz(void) + write_sequnlock_irqrestore(&vsyscall_gtod_data.lock, flags); + } + +-void update_vsyscall(struct timespec *wall_time, struct clocksource *clock) ++void update_vsyscall(struct timespec *wall_time, struct clocksource *clock, ++ u32 mult) + { + unsigned long flags; + +@@ -82,7 +83,7 @@ void update_vsyscall(struct timespec *wa + vsyscall_gtod_data.clock.vread = clock->vread; + vsyscall_gtod_data.clock.cycle_last = clock->cycle_last; + vsyscall_gtod_data.clock.mask = clock->mask; +- vsyscall_gtod_data.clock.mult = clock->mult; ++ vsyscall_gtod_data.clock.mult = mult; + vsyscall_gtod_data.clock.shift = clock->shift; + vsyscall_gtod_data.wall_time_sec = wall_time->tv_sec; + vsyscall_gtod_data.wall_time_nsec = wall_time->tv_nsec; +--- a/include/linux/clocksource.h ++++ b/include/linux/clocksource.h +@@ -282,10 +282,12 @@ extern struct clocksource * __init __wea + extern void clocksource_mark_unstable(struct clocksource *cs); + + #ifdef CONFIG_GENERIC_TIME_VSYSCALL +-extern void update_vsyscall(struct timespec *ts, struct clocksource *c); ++extern void ++update_vsyscall(struct timespec *ts, struct clocksource *c, u32 mult); + extern void update_vsyscall_tz(void); + #else +-static inline void update_vsyscall(struct timespec *ts, struct clocksource *c) ++static inline void ++update_vsyscall(struct timespec *ts, struct clocksource *c, u32 mult) + { + } + +--- a/kernel/time/timekeeping.c ++++ b/kernel/time/timekeeping.c +@@ -177,7 +177,7 @@ void timekeeping_leap_insert(int leapsec + { + xtime.tv_sec += leapsecond; + wall_to_monotonic.tv_sec -= leapsecond; +- update_vsyscall(&xtime, timekeeper.clock); ++ update_vsyscall(&xtime, timekeeper.clock, timekeeper.mult); + } + + #ifdef CONFIG_GENERIC_TIME +@@ -337,7 +337,7 @@ int do_settimeofday(struct timespec *tv) + timekeeper.ntp_error = 0; + ntp_clear(); + +- update_vsyscall(&xtime, timekeeper.clock); ++ update_vsyscall(&xtime, timekeeper.clock, timekeeper.mult); + + write_sequnlock_irqrestore(&xtime_lock, flags); + +@@ -822,7 +822,7 @@ void update_wall_time(void) + update_xtime_cache(nsecs); + + /* check to see if there is a new clocksource to use */ +- update_vsyscall(&xtime, timekeeper.clock); ++ update_vsyscall(&xtime, timekeeper.clock, timekeeper.mult); + } + + /** diff --git a/i386_defconfig-server b/i386_defconfig-server new file mode 100644 index 0000000..9e29f21 --- /dev/null +++ b/i386_defconfig-server @@ -0,0 +1,4826 @@ +# +# Automatically generated make config: don't edit +# +# CONFIG_64BIT is not set +CONFIG_X86_32=y +# CONFIG_X86_64 is not set +CONFIG_X86=y +CONFIG_OUTPUT_FORMAT="elf32-i386" +CONFIG_ARCH_DEFCONFIG="arch/x86/configs/i386_defconfig" +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CMOS_UPDATE=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_MMU=y +CONFIG_ZONE_DMA=y +CONFIG_GENERIC_ISA_DMA=y +CONFIG_GENERIC_IOMAP=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_GPIO=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +# CONFIG_RWSEM_GENERIC_SPINLOCK is not set +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +# CONFIG_GENERIC_TIME_VSYSCALL is not set +CONFIG_ARCH_HAS_CPU_RELAX=y +CONFIG_ARCH_HAS_DEFAULT_IDLE=y +CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y +CONFIG_HAVE_SETUP_PER_CPU_AREA=y +CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y +CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y +# CONFIG_HAVE_CPUMASK_OF_CPU_MAP is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +# CONFIG_ZONE_DMA32 is not set +CONFIG_ARCH_POPULATES_NODE_MAP=y +# CONFIG_AUDIT_ARCH is not set +CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y +CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_PENDING_IRQ=y +CONFIG_USE_GENERIC_SMP_HELPERS=y +CONFIG_X86_32_SMP=y +CONFIG_X86_NO_TSS=y +CONFIG_X86_NO_IDT=y +CONFIG_X86_32_LAZY_GS=y +CONFIG_KTIME_SCALAR=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_CONSTRUCTORS=y + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="-xen" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_HAVE_KERNEL_GZIP=y +CONFIG_KERNEL_GZIP=y +# CONFIG_KERNEL_BZIP2 is not set +# CONFIG_KERNEL_LZMA is not set +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_POSIX_MQUEUE=y +CONFIG_POSIX_MQUEUE_SYSCTL=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_TASK_XACCT=y +CONFIG_TASK_IO_ACCOUNTING=y +CONFIG_AUDIT=y +CONFIG_AUDITSYSCALL=y +CONFIG_AUDIT_TREE=y + +# +# RCU Subsystem +# +CONFIG_TREE_RCU=y +# CONFIG_TREE_PREEMPT_RCU is not set +# CONFIG_RCU_TRACE is not set +CONFIG_RCU_FANOUT=32 +# CONFIG_RCU_FANOUT_EXACT is not set +# CONFIG_TREE_RCU_TRACE is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=18 +CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y +CONFIG_GROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +CONFIG_RT_GROUP_SCHED=y +# CONFIG_USER_SCHED is not set +CONFIG_CGROUP_SCHED=y +CONFIG_CGROUPS=y +# CONFIG_CGROUP_DEBUG is not set +CONFIG_CGROUP_NS=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_DEVICE=y +CONFIG_CPUSETS=y +CONFIG_PROC_PID_CPUSET=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_RESOURCE_COUNTERS=y +CONFIG_CGROUP_MEM_RES_CTLR=y +# CONFIG_CGROUP_MEM_RES_CTLR_SWAP is not set +CONFIG_MM_OWNER=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set +CONFIG_RELAY=y +CONFIG_NAMESPACES=y +CONFIG_UTS_NS=y +CONFIG_IPC_NS=y +CONFIG_USER_NS=y +CONFIG_PID_NS=y +CONFIG_NET_NS=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +CONFIG_RD_BZIP2=y +CONFIG_RD_LZMA=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +# CONFIG_EMBEDDED is not set +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_ALL=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_PCSPKR_PLATFORM=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y + +# +# Kernel Performance Events And Counters +# +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_PCI_QUIRKS=y +CONFIG_COMPAT_BRK=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +CONFIG_PROFILING=y +CONFIG_OPROFILE=m +# CONFIG_OPROFILE_EVENT_MULTIPLEX is not set +CONFIG_HAVE_OPROFILE=y +CONFIG_KPROBES=y +CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y +CONFIG_KRETPROBES=y +CONFIG_HAVE_IOREMAP_PROT=y +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +CONFIG_HAVE_DMA_ATTRS=y +CONFIG_HAVE_DMA_API_DEBUG=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +CONFIG_SLOW_WORK=y +CONFIG_SLOW_WORK_DEBUG=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +CONFIG_MODULE_FORCE_LOAD=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_STOP_MACHINE=y +CONFIG_BLOCK=y +CONFIG_LBDAF=y +CONFIG_BLK_DEV_BSG=y +CONFIG_BLK_DEV_INTEGRITY=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +CONFIG_FREEZER=y + +# +# Processor type and features +# +CONFIG_SMP=y +CONFIG_SPARSE_IRQ=y +CONFIG_X86_MPPARSE=y +CONFIG_X86_XEN=y +CONFIG_X86_SUPPORTS_MEMORY_FAILURE=y +CONFIG_SCHED_OMIT_FRAME_POINTER=y +# CONFIG_M386 is not set +# CONFIG_M486 is not set +# CONFIG_M586 is not set +# CONFIG_M586TSC is not set +# CONFIG_M586MMX is not set +CONFIG_M686=y +# CONFIG_MPENTIUMII is not set +# CONFIG_MPENTIUMIII is not set +# CONFIG_MPENTIUMM is not set +# CONFIG_MPENTIUM4 is not set +# CONFIG_MK6 is not set +# CONFIG_MK7 is not set +# CONFIG_MK8 is not set +# CONFIG_MCRUSOE is not set +# CONFIG_MEFFICEON is not set +# CONFIG_MWINCHIPC6 is not set +# CONFIG_MWINCHIP3D is not set +# CONFIG_MGEODEGX1 is not set +# CONFIG_MGEODE_LX is not set +# CONFIG_MCYRIXIII is not set +# CONFIG_MVIAC3_2 is not set +# CONFIG_MVIAC7 is not set +# CONFIG_MPSC is not set +# CONFIG_MCORE2 is not set +# CONFIG_MATOM is not set +# CONFIG_GENERIC_CPU is not set +CONFIG_X86_GENERIC=y +CONFIG_X86_CPU=y +CONFIG_X86_L1_CACHE_BYTES=64 +CONFIG_X86_INTERNODE_CACHE_BYTES=64 +CONFIG_X86_CMPXCHG=y +CONFIG_X86_L1_CACHE_SHIFT=5 +CONFIG_X86_XADD=y +# CONFIG_X86_PPRO_FENCE is not set +CONFIG_X86_WP_WORKS_OK=y +CONFIG_X86_INVLPG=y +CONFIG_X86_BSWAP=y +CONFIG_X86_POPAD_OK=y +CONFIG_X86_INTEL_USERCOPY=y +CONFIG_X86_USE_PPRO_CHECKSUM=y +CONFIG_X86_CMPXCHG64=y +CONFIG_X86_CMOV=y +CONFIG_X86_MINIMUM_CPU_FAMILY=5 +CONFIG_X86_DEBUGCTLMSR=y +CONFIG_CPU_SUP_INTEL=y +CONFIG_CPU_SUP_CYRIX_32=y +CONFIG_CPU_SUP_AMD=y +CONFIG_CPU_SUP_CENTAUR=y +CONFIG_CPU_SUP_TRANSMETA_32=y +CONFIG_DMI=y +CONFIG_SWIOTLB=y +CONFIG_IOMMU_HELPER=y +# CONFIG_IOMMU_API is not set +CONFIG_NR_CPUS=32 +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_X86_LOCAL_APIC=y +CONFIG_X86_IO_APIC=y +CONFIG_X86_MCE=y +CONFIG_X86_MCE_INJECT=m +CONFIG_X86_XEN_MCE=y +CONFIG_VM86=y +CONFIG_TOSHIBA=m +CONFIG_I8K=m +CONFIG_MICROCODE=m +CONFIG_MICROCODE_OLD_INTERFACE=y +CONFIG_X86_MSR=m +CONFIG_X86_CPUID=m +# CONFIG_NOHIGHMEM is not set +# CONFIG_HIGHMEM4G is not set +CONFIG_HIGHMEM64G=y +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_HIGHMEM=y +CONFIG_X86_PAE=y +CONFIG_ARCH_PHYS_ADDR_T_64BIT=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_PHYS_ADDR_T_64BIT=y +CONFIG_ZONE_DMA_FLAG=1 +CONFIG_BOUNCE=y +CONFIG_VIRT_TO_BUS=y +CONFIG_HAVE_MLOCK=y +CONFIG_HAVE_MLOCKED_PAGE_BIT=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=65536 +CONFIG_ARCH_SUPPORTS_MEMORY_FAILURE=y +CONFIG_MEMORY_FAILURE=y +CONFIG_HWPOISON_INJECT=m +CONFIG_TMEM=y +CONFIG_PRECACHE=y +CONFIG_PRESWAP=y +# CONFIG_HIGHPTE is not set +CONFIG_MTRR=y +CONFIG_X86_PAT=y +CONFIG_ARCH_USES_PG_UNCACHED=y +CONFIG_SECCOMP=y +# CONFIG_CC_STACKPROTECTOR is not set +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_300 is not set +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +# CONFIG_SCHED_HRTICK is not set +CONFIG_KEXEC=y +CONFIG_PHYSICAL_START=0x2000 +CONFIG_PHYSICAL_ALIGN=0x2000 +CONFIG_HOTPLUG_CPU=y +CONFIG_COMPAT_VDSO=y +# CONFIG_CMDLINE_BOOL is not set + +# +# Power management and ACPI options +# +CONFIG_PM=y +CONFIG_PM_DEBUG=y +# CONFIG_PM_VERBOSE is not set +CONFIG_CAN_PM_TRACE=y +CONFIG_PM_TRACE=y +CONFIG_PM_TRACE_RTC=y +CONFIG_PM_SLEEP_SMP=y +CONFIG_PM_SLEEP=y +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +CONFIG_PM_RUNTIME=y +CONFIG_ACPI=y +CONFIG_ACPI_SLEEP=y +CONFIG_ACPI_PROCFS=y +CONFIG_ACPI_PROCFS_POWER=y +CONFIG_ACPI_POWER_METER=m +CONFIG_ACPI_SYSFS_POWER=y +CONFIG_ACPI_PROC_EVENT=y +CONFIG_ACPI_AC=m +CONFIG_ACPI_BATTERY=m +CONFIG_ACPI_BUTTON=m +CONFIG_ACPI_VIDEO=m +CONFIG_ACPI_FAN=m +CONFIG_ACPI_DOCK=y +CONFIG_ACPI_PROCESSOR=m +CONFIG_ACPI_HOTPLUG_CPU=y +CONFIG_ACPI_PROCESSOR_AGGREGATOR=m +CONFIG_ACPI_THERMAL=m +CONFIG_ACPI_CUSTOM_DSDT_FILE="" +# CONFIG_ACPI_CUSTOM_DSDT is not set +CONFIG_ACPI_BLACKLIST_YEAR=0 +CONFIG_ACPI_DEBUG=y +# CONFIG_ACPI_DEBUG_FUNC_TRACE is not set +CONFIG_ACPI_PCI_SLOT=m +CONFIG_ACPI_CONTAINER=m +CONFIG_ACPI_SBS=m +CONFIG_ACPI_PV_SLEEP=y +CONFIG_PROCESSOR_EXTERNAL_CONTROL=y +CONFIG_SFI=y + +# +# CPU Frequency scaling +# + +# +# Bus options (PCI etc.) +# +CONFIG_PCI=y +# CONFIG_PCI_GOBIOS is not set +# CONFIG_PCI_GOMMCONFIG is not set +# CONFIG_PCI_GODIRECT is not set +# CONFIG_PCI_GOOLPC is not set +# CONFIG_PCI_GOXEN_FE is not set +CONFIG_PCI_GOANY=y +CONFIG_PCI_DIRECT=y +CONFIG_PCI_MMCONFIG=y +CONFIG_PCI_OLPC=y +CONFIG_PCI_DOMAINS=y +CONFIG_XEN_PCIDEV_FRONTEND=y +# CONFIG_XEN_PCIDEV_FE_DEBUG is not set +CONFIG_PCIEPORTBUS=y +CONFIG_HOTPLUG_PCI_PCIE=m +CONFIG_PCIEAER=y +# CONFIG_PCIE_ECRC is not set +CONFIG_PCIEAER_INJECT=m +CONFIG_PCIEASPM=y +# CONFIG_PCIEASPM_DEBUG is not set +CONFIG_ARCH_SUPPORTS_MSI=y +CONFIG_PCI_MSI=y +CONFIG_PCI_LEGACY=y +# CONFIG_PCI_DEBUG is not set +CONFIG_PCI_GUESTDEV=y +CONFIG_PCI_IOMULTI=y +CONFIG_PCI_RESERVE=y +CONFIG_PCI_STUB=y +CONFIG_PCI_IOV=y +CONFIG_ISA_DMA_API=y +CONFIG_SCx200=m +CONFIG_SCx200HR_TIMER=m +CONFIG_OLPC=y +CONFIG_K8_NB=y +CONFIG_PCCARD=m +# CONFIG_PCMCIA_DEBUG is not set +CONFIG_PCMCIA=m +CONFIG_PCMCIA_LOAD_CIS=y +CONFIG_PCMCIA_IOCTL=y +CONFIG_CARDBUS=y + +# +# PC-card bridges +# +CONFIG_YENTA=m +CONFIG_YENTA_O2=y +CONFIG_YENTA_RICOH=y +CONFIG_YENTA_TI=y +CONFIG_YENTA_ENE_TUNE=y +CONFIG_YENTA_TOSHIBA=y +CONFIG_PD6729=m +CONFIG_I82092=m +CONFIG_PCCARD_NONSTATIC=m +CONFIG_HOTPLUG_PCI=m +CONFIG_HOTPLUG_PCI_FAKE=m +CONFIG_HOTPLUG_PCI_ACPI=m +CONFIG_HOTPLUG_PCI_ACPI_IBM=m +CONFIG_HOTPLUG_PCI_CPCI=y +CONFIG_HOTPLUG_PCI_CPCI_ZT5550=m +CONFIG_HOTPLUG_PCI_CPCI_GENERIC=m +CONFIG_HOTPLUG_PCI_SHPC=m + +# +# Executable file formats / Emulations +# +CONFIG_BINFMT_ELF=y +CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y +CONFIG_HAVE_AOUT=y +CONFIG_BINFMT_AOUT=m +CONFIG_BINFMT_MISC=m +CONFIG_HAVE_ATOMIC_IOMAP=y +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=m +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +CONFIG_XFRM_USER=m +CONFIG_XFRM_SUB_POLICY=y +CONFIG_XFRM_MIGRATE=y +# CONFIG_XFRM_STATISTICS is not set +CONFIG_XFRM_IPCOMP=m +CONFIG_NET_KEY=m +CONFIG_NET_KEY_MIGRATE=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_ASK_IP_FIB_HASH=y +# CONFIG_IP_FIB_TRIE is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=y +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +CONFIG_INET_XFRM_TUNNEL=m +CONFIG_INET_TUNNEL=m +CONFIG_INET_XFRM_MODE_TRANSPORT=m +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_XFRM_MODE_BEET=m +CONFIG_INET_LRO=y +CONFIG_INET_DIAG=m +CONFIG_INET_TCP_DIAG=m +CONFIG_TCP_CONG_ADVANCED=y +CONFIG_TCP_CONG_BIC=m +CONFIG_TCP_CONG_CUBIC=y +CONFIG_TCP_CONG_WESTWOOD=m +CONFIG_TCP_CONG_HTCP=m +CONFIG_TCP_CONG_HSTCP=m +CONFIG_TCP_CONG_HYBLA=m +CONFIG_TCP_CONG_VEGAS=m +CONFIG_TCP_CONG_SCALABLE=m +CONFIG_TCP_CONG_LP=m +CONFIG_TCP_CONG_VENO=m +CONFIG_TCP_CONG_YEAH=m +CONFIG_TCP_CONG_ILLINOIS=m +# CONFIG_DEFAULT_BIC is not set +CONFIG_DEFAULT_CUBIC=y +# CONFIG_DEFAULT_HTCP is not set +# CONFIG_DEFAULT_VEGAS is not set +# CONFIG_DEFAULT_WESTWOOD is not set +# CONFIG_DEFAULT_RENO is not set +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +CONFIG_IPV6=m +CONFIG_IPV6_PRIVACY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +# CONFIG_IPV6_OPTIMISTIC_DAD is not set +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_IPV6_MIP6=m +CONFIG_INET6_XFRM_TUNNEL=m +CONFIG_INET6_TUNNEL=m +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_INET6_XFRM_MODE_BEET=m +CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m +CONFIG_IPV6_SIT=m +CONFIG_IPV6_NDISC_NODETYPE=y +CONFIG_IPV6_TUNNEL=m +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +# CONFIG_IPV6_MROUTE is not set +CONFIG_NETLABEL=y +CONFIG_NETWORK_SECMARK=y +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_NETFILTER_ADVANCED=y +CONFIG_BRIDGE_NETFILTER=y + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_NETLINK=m +CONFIG_NETFILTER_NETLINK_QUEUE=m +CONFIG_NETFILTER_NETLINK_LOG=m +CONFIG_NF_CONNTRACK=m +CONFIG_NF_CT_ACCT=y +CONFIG_NF_CONNTRACK_MARK=y +CONFIG_NF_CONNTRACK_SECMARK=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CT_PROTO_DCCP=m +CONFIG_NF_CT_PROTO_GRE=m +CONFIG_NF_CT_PROTO_SCTP=m +CONFIG_NF_CT_PROTO_UDPLITE=m +CONFIG_NF_CONNTRACK_AMANDA=m +CONFIG_NF_CONNTRACK_FTP=m +CONFIG_NF_CONNTRACK_H323=m +CONFIG_NF_CONNTRACK_IRC=m +CONFIG_NF_CONNTRACK_NETBIOS_NS=m +CONFIG_NF_CONNTRACK_PPTP=m +CONFIG_NF_CONNTRACK_SANE=m +CONFIG_NF_CONNTRACK_SIP=m +CONFIG_NF_CONNTRACK_TFTP=m +CONFIG_NF_CT_NETLINK=m +CONFIG_NETFILTER_TPROXY=m +CONFIG_NETFILTER_XTABLES=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m +CONFIG_NETFILTER_XT_TARGET_DSCP=m +CONFIG_NETFILTER_XT_TARGET_HL=m +CONFIG_NETFILTER_XT_TARGET_LED=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFLOG=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_TARGET_RATEEST=m +CONFIG_NETFILTER_XT_TARGET_TPROXY=m +CONFIG_NETFILTER_XT_TARGET_TRACE=m +CONFIG_NETFILTER_XT_TARGET_SECMARK=m +CONFIG_NETFILTER_XT_TARGET_TCPMSS=m +CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m +CONFIG_NETFILTER_XT_MATCH_CLUSTER=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_DSCP=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_HL=m +CONFIG_NETFILTER_XT_MATCH_IPRANGE=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_OWNER=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_RATEEST=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_RECENT=m +# CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT is not set +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_SOCKET=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m +CONFIG_NETFILTER_XT_MATCH_TIME=m +CONFIG_NETFILTER_XT_MATCH_U32=m +CONFIG_NETFILTER_XT_MATCH_OSF=m +CONFIG_IP_VS=m +CONFIG_IP_VS_IPV6=y +# CONFIG_IP_VS_DEBUG is not set +CONFIG_IP_VS_TAB_BITS=12 + +# +# IPVS transport protocol load balancing support +# +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_AH_ESP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y + +# +# IPVS scheduler +# +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m + +# +# IPVS application helper +# +CONFIG_IP_VS_FTP=m + +# +# IP: Netfilter Configuration +# +CONFIG_NF_DEFRAG_IPV4=m +CONFIG_NF_CONNTRACK_IPV4=m +# CONFIG_NF_CONNTRACK_PROC_COMPAT is not set +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_ADDRTYPE=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_NF_NAT=m +CONFIG_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_NF_NAT_SNMP_BASIC=m +CONFIG_NF_NAT_PROTO_DCCP=m +CONFIG_NF_NAT_PROTO_GRE=m +CONFIG_NF_NAT_PROTO_UDPLITE=m +CONFIG_NF_NAT_PROTO_SCTP=m +CONFIG_NF_NAT_FTP=m +CONFIG_NF_NAT_IRC=m +CONFIG_NF_NAT_TFTP=m +CONFIG_NF_NAT_AMANDA=m +CONFIG_NF_NAT_PPTP=m +CONFIG_NF_NAT_H323=m +CONFIG_NF_NAT_SIP=m +CONFIG_IP_NF_MANGLE=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_TARGET_TTL=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_SECURITY=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m + +# +# IPv6: Netfilter Configuration +# +CONFIG_NF_CONNTRACK_IPV6=m +CONFIG_IP6_NF_QUEUE=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_MH=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_TARGET_LOG=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_RAW=m +CONFIG_IP6_NF_SECURITY=m + +# +# DECnet: Netfilter Configuration +# +# CONFIG_DECNET_NF_GRABULATOR is not set +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_IP6=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_ULOG=m +CONFIG_BRIDGE_EBT_NFLOG=m +CONFIG_IP_DCCP=m +CONFIG_INET_DCCP_DIAG=m + +# +# DCCP CCIDs Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP_CCID2_DEBUG is not set +CONFIG_IP_DCCP_CCID3=y +# CONFIG_IP_DCCP_CCID3_DEBUG is not set +CONFIG_IP_DCCP_CCID3_RTO=100 +CONFIG_IP_DCCP_TFRC_LIB=y + +# +# DCCP Kernel Hacking +# +# CONFIG_IP_DCCP_DEBUG is not set +# CONFIG_NET_DCCPPROBE is not set +CONFIG_IP_SCTP=m +# CONFIG_SCTP_DBG_MSG is not set +# CONFIG_SCTP_DBG_OBJCNT is not set +# CONFIG_SCTP_HMAC_NONE is not set +# CONFIG_SCTP_HMAC_SHA1 is not set +CONFIG_SCTP_HMAC_MD5=y +CONFIG_RDS=m +CONFIG_RDS_RDMA=m +CONFIG_RDS_TCP=m +# CONFIG_RDS_DEBUG is not set +# CONFIG_TIPC is not set +CONFIG_ATM=m +CONFIG_ATM_CLIP=m +# CONFIG_ATM_CLIP_NO_ICMP is not set +CONFIG_ATM_LANE=m +CONFIG_ATM_MPOA=m +CONFIG_ATM_BR2684=m +# CONFIG_ATM_BR2684_IPFILTER is not set +CONFIG_STP=m +CONFIG_GARP=m +CONFIG_BRIDGE=m +CONFIG_NET_DSA=y +CONFIG_NET_DSA_TAG_DSA=y +CONFIG_NET_DSA_TAG_EDSA=y +CONFIG_NET_DSA_TAG_TRAILER=y +CONFIG_NET_DSA_MV88E6XXX=y +CONFIG_NET_DSA_MV88E6060=y +CONFIG_NET_DSA_MV88E6XXX_NEED_PPU=y +CONFIG_NET_DSA_MV88E6131=y +CONFIG_NET_DSA_MV88E6123_61_65=y +CONFIG_VLAN_8021Q=m +CONFIG_VLAN_8021Q_GVRP=y +CONFIG_DECNET=m +# CONFIG_DECNET_ROUTER is not set +CONFIG_LLC=m +CONFIG_LLC2=m +CONFIG_IPX=m +CONFIG_IPX_INTERN=y +CONFIG_ATALK=m +CONFIG_DEV_APPLETALK=m +CONFIG_IPDDP=m +CONFIG_IPDDP_ENCAP=y +CONFIG_IPDDP_DECAP=y +CONFIG_X25=m +CONFIG_LAPB=m +# CONFIG_ECONET is not set +CONFIG_WAN_ROUTER=m +CONFIG_PHONET=m +CONFIG_IEEE802154=m +CONFIG_NET_SCHED=y + +# +# Queueing/Scheduling +# +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_ATM=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_MULTIQ=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_DRR=m +CONFIG_NET_SCH_INGRESS=m + +# +# Classification +# +CONFIG_NET_CLS=y +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_ROUTE=y +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_CLS_FLOW=m +CONFIG_NET_CLS_CGROUP=y +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_STACK=32 +CONFIG_NET_EMATCH_CMP=m +CONFIG_NET_EMATCH_NBYTE=m +CONFIG_NET_EMATCH_U32=m +CONFIG_NET_EMATCH_META=m +CONFIG_NET_EMATCH_TEXT=m +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=m +CONFIG_NET_ACT_GACT=m +CONFIG_GACT_PROB=y +CONFIG_NET_ACT_MIRRED=m +CONFIG_NET_ACT_IPT=m +CONFIG_NET_ACT_NAT=m +CONFIG_NET_ACT_PEDIT=m +CONFIG_NET_ACT_SIMP=m +CONFIG_NET_ACT_SKBEDIT=m +CONFIG_NET_CLS_IND=y +CONFIG_NET_SCH_FIFO=y +CONFIG_DCB=y + +# +# Network testing +# +CONFIG_NET_PKTGEN=m +CONFIG_NET_TCPPROBE=m +CONFIG_HAMRADIO=y + +# +# Packet Radio protocols +# +CONFIG_AX25=m +CONFIG_AX25_DAMA_SLAVE=y +CONFIG_NETROM=m +CONFIG_ROSE=m + +# +# AX.25 network device drivers +# +CONFIG_MKISS=m +CONFIG_6PACK=m +CONFIG_BPQETHER=m +CONFIG_BAYCOM_SER_FDX=m +CONFIG_BAYCOM_SER_HDX=m +CONFIG_BAYCOM_PAR=m +CONFIG_BAYCOM_EPP=m +CONFIG_YAM=m +CONFIG_CAN=m +CONFIG_CAN_RAW=m +CONFIG_CAN_BCM=m + +# +# CAN Device Drivers +# +CONFIG_CAN_VCAN=m +CONFIG_CAN_DEV=m +CONFIG_CAN_CALC_BITTIMING=y +CONFIG_CAN_SJA1000=m +CONFIG_CAN_SJA1000_PLATFORM=m +CONFIG_CAN_EMS_PCI=m +CONFIG_CAN_KVASER_PCI=m + +# +# CAN USB interfaces +# +CONFIG_CAN_EMS_USB=m +# CONFIG_CAN_DEBUG_DEVICES is not set +CONFIG_IRDA=m + +# +# IrDA protocols +# +CONFIG_IRLAN=m +CONFIG_IRNET=m +CONFIG_IRCOMM=m +CONFIG_IRDA_ULTRA=y + +# +# IrDA options +# +CONFIG_IRDA_CACHE_LAST_LSAP=y +# CONFIG_IRDA_FAST_RR is not set +# CONFIG_IRDA_DEBUG is not set + +# +# Infrared-port device drivers +# + +# +# SIR device drivers +# +CONFIG_IRTTY_SIR=m + +# +# Dongle support +# +CONFIG_DONGLE=y +CONFIG_ESI_DONGLE=m +CONFIG_ACTISYS_DONGLE=m +CONFIG_TEKRAM_DONGLE=m +CONFIG_TOIM3232_DONGLE=m +CONFIG_LITELINK_DONGLE=m +CONFIG_MA600_DONGLE=m +CONFIG_GIRBIL_DONGLE=m +CONFIG_MCP2120_DONGLE=m +CONFIG_OLD_BELKIN_DONGLE=m +CONFIG_ACT200L_DONGLE=m +CONFIG_KINGSUN_DONGLE=m +CONFIG_KSDAZZLE_DONGLE=m +CONFIG_KS959_DONGLE=m + +# +# FIR device drivers +# +CONFIG_USB_IRDA=m +CONFIG_SIGMATEL_FIR=m +CONFIG_NSC_FIR=m +CONFIG_WINBOND_FIR=m +CONFIG_TOSHIBA_FIR=m +CONFIG_SMC_IRCC_FIR=m +CONFIG_ALI_FIR=m +CONFIG_VLSI_FIR=m +CONFIG_VIA_FIR=m +CONFIG_MCS_FIR=m +CONFIG_BT=m +CONFIG_BT_L2CAP=m +CONFIG_BT_SCO=m +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_CMTP=m +CONFIG_BT_HIDP=m + +# +# Bluetooth device drivers +# +CONFIG_BT_HCIBTUSB=m +CONFIG_BT_HCIBTSDIO=m +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_H4=y +CONFIG_BT_HCIUART_BCSP=y +CONFIG_BT_HCIUART_LL=y +CONFIG_BT_HCIBCM203X=m +CONFIG_BT_HCIBPA10X=m +CONFIG_BT_HCIBFUSB=m +CONFIG_BT_HCIDTL1=m +CONFIG_BT_HCIBT3C=m +CONFIG_BT_HCIBLUECARD=m +CONFIG_BT_HCIBTUART=m +CONFIG_BT_HCIVHCI=m +CONFIG_BT_MRVL=m +CONFIG_BT_MRVL_SDIO=m +CONFIG_AF_RXRPC=m +# CONFIG_AF_RXRPC_DEBUG is not set +CONFIG_RXKAD=m +CONFIG_FIB_RULES=y +CONFIG_WIRELESS=y +CONFIG_CFG80211=m +# CONFIG_NL80211_TESTMODE is not set +# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set +# CONFIG_CFG80211_REG_DEBUG is not set +CONFIG_CFG80211_DEFAULT_PS=y +CONFIG_CFG80211_DEFAULT_PS_VALUE=1 +# CONFIG_CFG80211_DEBUGFS is not set +# CONFIG_WIRELESS_OLD_REGULATORY is not set +CONFIG_WIRELESS_EXT=y +CONFIG_WIRELESS_EXT_SYSFS=y +CONFIG_LIB80211=m +CONFIG_LIB80211_CRYPT_WEP=m +CONFIG_LIB80211_CRYPT_CCMP=m +CONFIG_LIB80211_CRYPT_TKIP=m +# CONFIG_LIB80211_DEBUG is not set +CONFIG_MAC80211=m +CONFIG_MAC80211_RC_MINSTREL=y +# CONFIG_MAC80211_RC_DEFAULT_PID is not set +CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y +CONFIG_MAC80211_RC_DEFAULT="minstrel" +CONFIG_MAC80211_MESH=y +CONFIG_MAC80211_LEDS=y +CONFIG_MAC80211_DEBUGFS=y +# CONFIG_MAC80211_DEBUG_MENU is not set +CONFIG_WIMAX=m +CONFIG_WIMAX_DEBUG_LEVEL=8 +CONFIG_RFKILL=m +CONFIG_RFKILL_LEDS=y +CONFIG_RFKILL_INPUT=y +CONFIG_NET_9P=m +CONFIG_NET_9P_RDMA=m +# CONFIG_NET_9P_DEBUG is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +# CONFIG_STANDALONE is not set +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +CONFIG_SYS_HYPERVISOR=y +CONFIG_CONNECTOR=y +CONFIG_PROC_EVENTS=y +CONFIG_MTD=m +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_TESTS=m +CONFIG_MTD_CONCAT=m +CONFIG_MTD_PARTITIONS=y +CONFIG_MTD_REDBOOT_PARTS=m +CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 +# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set +# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set +CONFIG_MTD_AR7_PARTS=m + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=m +CONFIG_HAVE_MTD_OTP=y +CONFIG_MTD_BLKDEVS=m +CONFIG_MTD_BLOCK=m +CONFIG_MTD_BLOCK_RO=m +CONFIG_FTL=m +CONFIG_NFTL=m +CONFIG_NFTL_RW=y +CONFIG_INFTL=m +CONFIG_RFD_FTL=m +CONFIG_SSFDC=m +CONFIG_MTD_OOPS=m + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=m +CONFIG_MTD_JEDECPROBE=m +CONFIG_MTD_GEN_PROBE=m +CONFIG_MTD_CFI_ADV_OPTIONS=y +CONFIG_MTD_CFI_NOSWAP=y +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set +CONFIG_MTD_CFI_GEOMETRY=y +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +CONFIG_MTD_MAP_BANK_WIDTH_8=y +CONFIG_MTD_MAP_BANK_WIDTH_16=y +CONFIG_MTD_MAP_BANK_WIDTH_32=y +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +CONFIG_MTD_CFI_I4=y +CONFIG_MTD_CFI_I8=y +CONFIG_MTD_OTP=y +CONFIG_MTD_CFI_INTELEXT=m +CONFIG_MTD_CFI_AMDSTD=m +CONFIG_MTD_CFI_STAA=m +CONFIG_MTD_CFI_UTIL=m +CONFIG_MTD_RAM=m +CONFIG_MTD_ROM=m +CONFIG_MTD_ABSENT=m + +# +# Mapping drivers for chip access +# +CONFIG_MTD_COMPLEX_MAPPINGS=y +CONFIG_MTD_PHYSMAP=m +CONFIG_MTD_PHYSMAP_COMPAT=y +CONFIG_MTD_PHYSMAP_START=0x8000000 +CONFIG_MTD_PHYSMAP_LEN=0 +CONFIG_MTD_PHYSMAP_BANKWIDTH=2 +CONFIG_MTD_SC520CDP=m +CONFIG_MTD_NETSC520=m +CONFIG_MTD_TS5500=m +CONFIG_MTD_SBC_GXX=m +CONFIG_MTD_SCx200_DOCFLASH=m +CONFIG_MTD_AMD76XROM=m +CONFIG_MTD_ICHXROM=m +CONFIG_MTD_ESB2ROM=m +CONFIG_MTD_CK804XROM=m +CONFIG_MTD_SCB2_FLASH=m +CONFIG_MTD_NETtel=m +CONFIG_MTD_L440GX=m +CONFIG_MTD_PCI=m +CONFIG_MTD_GPIO_ADDR=m +CONFIG_MTD_INTEL_VR_NOR=m +CONFIG_MTD_PLATRAM=m + +# +# Self-contained MTD device drivers +# +CONFIG_MTD_PMC551=m +CONFIG_MTD_PMC551_BUGFIX=y +# CONFIG_MTD_PMC551_DEBUG is not set +CONFIG_MTD_DATAFLASH=m +CONFIG_MTD_DATAFLASH_WRITE_VERIFY=y +CONFIG_MTD_DATAFLASH_OTP=y +CONFIG_MTD_M25P80=m +CONFIG_M25PXX_USE_FAST_READ=y +CONFIG_MTD_SST25L=m +CONFIG_MTD_SLRAM=m +CONFIG_MTD_PHRAM=m +CONFIG_MTD_MTDRAM=m +CONFIG_MTDRAM_TOTAL_SIZE=4096 +CONFIG_MTDRAM_ERASE_SIZE=128 +CONFIG_MTD_BLOCK2MTD=m + +# +# Disk-On-Chip Device Drivers +# +CONFIG_MTD_DOC2000=m +CONFIG_MTD_DOC2001=m +CONFIG_MTD_DOC2001PLUS=m +CONFIG_MTD_DOCPROBE=m +CONFIG_MTD_DOCECC=m +CONFIG_MTD_DOCPROBE_ADVANCED=y +CONFIG_MTD_DOCPROBE_ADDRESS=0x0000 +CONFIG_MTD_DOCPROBE_HIGH=y +CONFIG_MTD_DOCPROBE_55AA=y +CONFIG_MTD_NAND=m +CONFIG_MTD_NAND_VERIFY_WRITE=y +CONFIG_MTD_NAND_ECC_SMC=y +CONFIG_MTD_NAND_MUSEUM_IDS=y +CONFIG_MTD_NAND_IDS=m +CONFIG_MTD_NAND_DISKONCHIP=m +CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED=y +CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0 +CONFIG_MTD_NAND_DISKONCHIP_PROBE_HIGH=y +CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE=y +CONFIG_MTD_NAND_CAFE=m +CONFIG_MTD_NAND_CS553X=m +CONFIG_MTD_NAND_NANDSIM=m +CONFIG_MTD_NAND_PLATFORM=m +CONFIG_MTD_ALAUDA=m +CONFIG_MTD_ONENAND=m +CONFIG_MTD_ONENAND_VERIFY_WRITE=y +CONFIG_MTD_ONENAND_GENERIC=m +CONFIG_MTD_ONENAND_OTP=y +CONFIG_MTD_ONENAND_2X_PROGRAM=y +CONFIG_MTD_ONENAND_SIM=m + +# +# LPDDR flash memory drivers +# +CONFIG_MTD_LPDDR=m +CONFIG_MTD_QINFO_PROBE=m + +# +# UBI - Unsorted block images +# +CONFIG_MTD_UBI=m +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_MTD_UBI_BEB_RESERVE=1 +CONFIG_MTD_UBI_GLUEBI=m + +# +# UBI debugging options +# +# CONFIG_MTD_UBI_DEBUG is not set +CONFIG_PARPORT=m +CONFIG_PARPORT_PC=m +CONFIG_PARPORT_SERIAL=m +CONFIG_PARPORT_PC_FIFO=y +CONFIG_PARPORT_PC_SUPERIO=y +CONFIG_PARPORT_PC_PCMCIA=m +# CONFIG_PARPORT_GSC is not set +CONFIG_PARPORT_AX88796=m +CONFIG_PARPORT_1284=y +CONFIG_PARPORT_NOT_PC=y +CONFIG_PNP=y +# CONFIG_PNP_DEBUG_MESSAGES is not set + +# +# Protocols +# +CONFIG_PNPACPI=y +CONFIG_BLK_DEV=y +CONFIG_BLK_DEV_FD=m +CONFIG_PARIDE=m + +# +# Parallel IDE high-level drivers +# +CONFIG_PARIDE_PD=m +CONFIG_PARIDE_PCD=m +CONFIG_PARIDE_PF=m +CONFIG_PARIDE_PT=m +CONFIG_PARIDE_PG=m + +# +# Parallel IDE protocol modules +# +CONFIG_PARIDE_ATEN=m +CONFIG_PARIDE_BPCK=m +CONFIG_PARIDE_BPCK6=m +CONFIG_PARIDE_COMM=m +CONFIG_PARIDE_DSTR=m +CONFIG_PARIDE_FIT2=m +CONFIG_PARIDE_FIT3=m +CONFIG_PARIDE_EPAT=m +CONFIG_PARIDE_EPATC8=y +CONFIG_PARIDE_EPIA=m +CONFIG_PARIDE_FRIQ=m +CONFIG_PARIDE_FRPW=m +CONFIG_PARIDE_KBIC=m +CONFIG_PARIDE_KTTI=m +CONFIG_PARIDE_ON20=m +CONFIG_PARIDE_ON26=m +CONFIG_BLK_CPQ_DA=m +CONFIG_BLK_CPQ_CISS_DA=m +CONFIG_CISS_SCSI_TAPE=y +CONFIG_BLK_DEV_DAC960=m +CONFIG_BLK_DEV_UMEM=m +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_OSD=m +CONFIG_BLK_DEV_SX8=m +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=m +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=131072 +CONFIG_BLK_DEV_XIP=y +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +CONFIG_CDROM_PKTCDVD_WCACHE=y +CONFIG_ATA_OVER_ETH=m +# CONFIG_BLK_DEV_HD is not set +CONFIG_MISC_DEVICES=y +CONFIG_IBM_ASM=m +CONFIG_PHANTOM=m +CONFIG_SGI_IOC4=m +CONFIG_TIFM_CORE=m +CONFIG_TIFM_7XX1=m +CONFIG_ICS932S401=m +CONFIG_ENCLOSURE_SERVICES=m +CONFIG_HP_ILO=m +CONFIG_DELL_LAPTOP=m +# CONFIG_ISL29003 is not set +CONFIG_C2PORT=m +CONFIG_C2PORT_DURAMAR_2150=m + +# +# EEPROM support +# +CONFIG_EEPROM_AT24=m +CONFIG_EEPROM_AT25=m +CONFIG_EEPROM_LEGACY=m +CONFIG_EEPROM_MAX6875=m +CONFIG_EEPROM_93CX6=m +CONFIG_CB710_CORE=m +# CONFIG_CB710_DEBUG is not set +CONFIG_CB710_DEBUG_ASSUMPTIONS=y +CONFIG_HAVE_IDE=y +CONFIG_IDE=m + +# +# Please see Documentation/ide/ide.txt for help/info on IDE drives +# +CONFIG_IDE_XFER_MODE=y +CONFIG_IDE_TIMINGS=y +CONFIG_IDE_ATAPI=y +# CONFIG_BLK_DEV_IDE_SATA is not set +CONFIG_IDE_GD=m +CONFIG_IDE_GD_ATA=y +CONFIG_IDE_GD_ATAPI=y +CONFIG_BLK_DEV_IDECS=m +CONFIG_BLK_DEV_DELKIN=m +CONFIG_BLK_DEV_IDECD=m +CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y +CONFIG_BLK_DEV_IDETAPE=m +CONFIG_BLK_DEV_IDEACPI=y +# CONFIG_IDE_TASK_IOCTL is not set +CONFIG_IDE_PROC_FS=y + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=m +CONFIG_BLK_DEV_PLATFORM=m +CONFIG_BLK_DEV_CMD640=m +CONFIG_BLK_DEV_CMD640_ENHANCED=y +CONFIG_BLK_DEV_IDEPNP=m +CONFIG_BLK_DEV_IDEDMA_SFF=y + +# +# PCI IDE chipsets support +# +CONFIG_BLK_DEV_IDEPCI=y +CONFIG_BLK_DEV_OFFBOARD=y +CONFIG_BLK_DEV_GENERIC=m +CONFIG_BLK_DEV_OPTI621=m +CONFIG_BLK_DEV_RZ1000=m +CONFIG_BLK_DEV_IDEDMA_PCI=y +CONFIG_BLK_DEV_AEC62XX=m +CONFIG_BLK_DEV_ALI15X3=m +CONFIG_BLK_DEV_AMD74XX=m +CONFIG_BLK_DEV_ATIIXP=m +CONFIG_BLK_DEV_CMD64X=m +CONFIG_BLK_DEV_TRIFLEX=m +CONFIG_BLK_DEV_CS5520=m +CONFIG_BLK_DEV_CS5530=m +CONFIG_BLK_DEV_CS5535=m +CONFIG_BLK_DEV_CS5536=m +CONFIG_BLK_DEV_HPT366=m +CONFIG_BLK_DEV_JMICRON=m +CONFIG_BLK_DEV_SC1200=m +CONFIG_BLK_DEV_PIIX=m +CONFIG_BLK_DEV_IT8172=m +CONFIG_BLK_DEV_IT8213=m +CONFIG_BLK_DEV_IT821X=m +CONFIG_BLK_DEV_NS87415=m +CONFIG_BLK_DEV_PDC202XX_OLD=m +CONFIG_BLK_DEV_PDC202XX_NEW=m +CONFIG_BLK_DEV_SVWKS=m +CONFIG_BLK_DEV_SIIMAGE=m +CONFIG_BLK_DEV_SIS5513=m +CONFIG_BLK_DEV_SLC90E66=m +# CONFIG_BLK_DEV_TRM290 is not set +CONFIG_BLK_DEV_VIA82CXXX=m +CONFIG_BLK_DEV_TC86C001=m +CONFIG_BLK_DEV_IDEDMA=y + +# +# SCSI device support +# +CONFIG_RAID_ATTRS=m +CONFIG_SCSI=m +CONFIG_SCSI_DMA=y +CONFIG_SCSI_TGT=m +CONFIG_SCSI_NETLINK=y +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=m +CONFIG_CHR_DEV_ST=m +CONFIG_CHR_DEV_OSST=m +CONFIG_BLK_DEV_SR=m +# CONFIG_BLK_DEV_SR_VENDOR is not set +CONFIG_CHR_DEV_SG=m +CONFIG_CHR_DEV_SCH=m +CONFIG_SCSI_ENCLOSURE=m +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m + +# +# SCSI Transports +# +CONFIG_SCSI_SPI_ATTRS=m +CONFIG_SCSI_FC_ATTRS=m +CONFIG_SCSI_FC_TGT_ATTRS=y +CONFIG_SCSI_ISCSI_ATTRS=m +CONFIG_SCSI_SAS_ATTRS=m +CONFIG_SCSI_SAS_LIBSAS=m +CONFIG_SCSI_SAS_ATA=y +CONFIG_SCSI_SAS_HOST_SMP=y +# CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set +CONFIG_SCSI_SRP_ATTRS=m +CONFIG_SCSI_SRP_TGT_ATTRS=y +CONFIG_SCSI_LOWLEVEL=y +CONFIG_ISCSI_TCP=m +CONFIG_SCSI_CXGB3_ISCSI=m +CONFIG_SCSI_BNX2_ISCSI=m +CONFIG_BE2ISCSI=m +CONFIG_BLK_DEV_3W_XXXX_RAID=m +CONFIG_SCSI_3W_9XXX=m +CONFIG_SCSI_ACARD=m +CONFIG_SCSI_AACRAID=m +CONFIG_SCSI_AIC7XXX=m +CONFIG_AIC7XXX_CMDS_PER_DEVICE=32 +CONFIG_AIC7XXX_RESET_DELAY_MS=15000 +# CONFIG_AIC7XXX_DEBUG_ENABLE is not set +CONFIG_AIC7XXX_DEBUG_MASK=0 +CONFIG_AIC7XXX_REG_PRETTY_PRINT=y +CONFIG_SCSI_AIC7XXX_OLD=m +CONFIG_SCSI_AIC79XX=m +CONFIG_AIC79XX_CMDS_PER_DEVICE=32 +CONFIG_AIC79XX_RESET_DELAY_MS=5000 +# CONFIG_AIC79XX_DEBUG_ENABLE is not set +CONFIG_AIC79XX_DEBUG_MASK=0 +CONFIG_AIC79XX_REG_PRETTY_PRINT=y +CONFIG_SCSI_AIC94XX=m +# CONFIG_AIC94XX_DEBUG is not set +CONFIG_SCSI_MVSAS=m +# CONFIG_SCSI_MVSAS_DEBUG is not set +CONFIG_SCSI_DPT_I2O=m +CONFIG_SCSI_ADVANSYS=m +CONFIG_SCSI_ARCMSR=m +CONFIG_SCSI_ARCMSR_AER=y +CONFIG_MEGARAID_NEWGEN=y +CONFIG_MEGARAID_MM=m +CONFIG_MEGARAID_MAILBOX=m +CONFIG_MEGARAID_LEGACY=m +CONFIG_MEGARAID_SAS=m +CONFIG_SCSI_MPT2SAS=m +CONFIG_SCSI_MPT2SAS_MAX_SGE=128 +# CONFIG_SCSI_MPT2SAS_LOGGING is not set +CONFIG_SCSI_HPTIOP=m +CONFIG_SCSI_BUSLOGIC=m +CONFIG_SCSI_FLASHPOINT=y +CONFIG_LIBFC=m +CONFIG_LIBFCOE=m +CONFIG_FCOE=m +CONFIG_FCOE_FNIC=m +CONFIG_SCSI_DMX3191D=m +CONFIG_SCSI_EATA=m +CONFIG_SCSI_EATA_TAGGED_QUEUE=y +CONFIG_SCSI_EATA_LINKED_COMMANDS=y +CONFIG_SCSI_EATA_MAX_TAGS=16 +CONFIG_SCSI_FUTURE_DOMAIN=m +CONFIG_SCSI_GDTH=m +CONFIG_SCSI_IPS=m +CONFIG_SCSI_INITIO=m +CONFIG_SCSI_INIA100=m +CONFIG_SCSI_PPA=m +CONFIG_SCSI_IMM=m +# CONFIG_SCSI_IZIP_EPP16 is not set +# CONFIG_SCSI_IZIP_SLOW_CTR is not set +CONFIG_SCSI_STEX=m +CONFIG_SCSI_SYM53C8XX_2=m +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +CONFIG_SCSI_SYM53C8XX_MMIO=y +CONFIG_SCSI_IPR=m +CONFIG_SCSI_IPR_TRACE=y +CONFIG_SCSI_IPR_DUMP=y +CONFIG_SCSI_QLOGIC_1280=m +CONFIG_SCSI_QLA_FC=m +CONFIG_SCSI_QLA_ISCSI=m +CONFIG_SCSI_LPFC=m +# CONFIG_SCSI_LPFC_DEBUG_FS is not set +CONFIG_SCSI_DC395x=m +CONFIG_SCSI_DC390T=m +CONFIG_SCSI_NSP32=m +CONFIG_SCSI_DEBUG=m +CONFIG_SCSI_PMCRAID=m +CONFIG_SCSI_SRP=m +CONFIG_SCSI_BFA_FC=m +CONFIG_SCSI_LOWLEVEL_PCMCIA=y +CONFIG_PCMCIA_AHA152X=m +CONFIG_PCMCIA_FDOMAIN=m +CONFIG_PCMCIA_NINJA_SCSI=m +CONFIG_PCMCIA_QLOGIC=m +CONFIG_PCMCIA_SYM53C500=m +CONFIG_SCSI_DH=m +CONFIG_SCSI_DH_RDAC=m +CONFIG_SCSI_DH_HP_SW=m +CONFIG_SCSI_DH_EMC=m +CONFIG_SCSI_DH_ALUA=m +CONFIG_SCSI_OSD_INITIATOR=m +CONFIG_SCSI_OSD_ULD=m +CONFIG_SCSI_OSD_DPRINT_SENSE=1 +# CONFIG_SCSI_OSD_DEBUG is not set +CONFIG_ATA=m +# CONFIG_ATA_NONSTANDARD is not set +CONFIG_ATA_VERBOSE_ERROR=y +CONFIG_ATA_ACPI=y +CONFIG_SATA_PMP=y +CONFIG_SATA_AHCI=m +CONFIG_SATA_SIL24=m +CONFIG_ATA_SFF=y +CONFIG_SATA_SVW=m +CONFIG_ATA_PIIX=m +CONFIG_SATA_MV=m +CONFIG_SATA_NV=m +CONFIG_PDC_ADMA=m +CONFIG_SATA_QSTOR=m +CONFIG_SATA_PROMISE=m +CONFIG_SATA_SX4=m +CONFIG_SATA_SIL=m +CONFIG_SATA_SIS=m +CONFIG_SATA_ULI=m +CONFIG_SATA_VIA=m +CONFIG_SATA_VITESSE=m +CONFIG_SATA_INIC162X=m +CONFIG_PATA_ACPI=m +CONFIG_PATA_ALI=m +CONFIG_PATA_AMD=m +CONFIG_PATA_ARTOP=m +CONFIG_PATA_ATP867X=m +CONFIG_PATA_ATIIXP=m +CONFIG_PATA_CMD640_PCI=m +CONFIG_PATA_CMD64X=m +CONFIG_PATA_CS5520=m +CONFIG_PATA_CS5530=m +CONFIG_PATA_CS5535=m +CONFIG_PATA_CS5536=m +CONFIG_PATA_CYPRESS=m +CONFIG_PATA_EFAR=m +CONFIG_ATA_GENERIC=m +CONFIG_PATA_HPT366=m +CONFIG_PATA_HPT37X=m +CONFIG_PATA_HPT3X2N=m +CONFIG_PATA_HPT3X3=m +# CONFIG_PATA_HPT3X3_DMA is not set +CONFIG_PATA_IT821X=m +CONFIG_PATA_IT8213=m +CONFIG_PATA_JMICRON=m +CONFIG_PATA_TRIFLEX=m +CONFIG_PATA_MARVELL=m +CONFIG_PATA_MPIIX=m +CONFIG_PATA_OLDPIIX=m +CONFIG_PATA_NETCELL=m +CONFIG_PATA_NINJA32=m +CONFIG_PATA_NS87410=m +CONFIG_PATA_NS87415=m +CONFIG_PATA_OPTI=m +CONFIG_PATA_OPTIDMA=m +CONFIG_PATA_PCMCIA=m +CONFIG_PATA_PDC_OLD=m +CONFIG_PATA_RADISYS=m +CONFIG_PATA_RDC=m +CONFIG_PATA_RZ1000=m +CONFIG_PATA_SC1200=m +CONFIG_PATA_SERVERWORKS=m +CONFIG_PATA_PDC2027X=m +CONFIG_PATA_SIL680=m +CONFIG_PATA_SIS=m +CONFIG_PATA_VIA=m +CONFIG_PATA_WINBOND=m +CONFIG_PATA_SCH=m +CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_AUTODETECT=y +CONFIG_MD_LINEAR=m +CONFIG_MD_RAID0=m +CONFIG_MD_RAID1=m +CONFIG_MD_RAID10=m +CONFIG_MD_RAID456=m +# CONFIG_MULTICORE_RAID456 is not set +CONFIG_MD_RAID6_PQ=m +CONFIG_ASYNC_RAID6_TEST=m +CONFIG_MD_MULTIPATH=m +CONFIG_MD_FAULTY=m +CONFIG_BLK_DEV_DM=m +# CONFIG_DM_DEBUG is not set +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_MIRROR=m +CONFIG_DM_LOG_USERSPACE=m +CONFIG_DM_ZERO=m +CONFIG_DM_MULTIPATH=m +CONFIG_DM_MULTIPATH_QL=m +CONFIG_DM_MULTIPATH_ST=m +CONFIG_DM_DELAY=m +CONFIG_DM_UEVENT=y +CONFIG_FUSION=y +CONFIG_FUSION_SPI=m +CONFIG_FUSION_FC=m +CONFIG_FUSION_SAS=m +CONFIG_FUSION_MAX_SGE=128 +CONFIG_FUSION_CTL=m +CONFIG_FUSION_LAN=m +# CONFIG_FUSION_LOGGING is not set + +# +# IEEE 1394 (FireWire) support +# + +# +# You can enable one or both FireWire driver stacks. +# + +# +# See the help texts for more information. +# +# CONFIG_FIREWIRE is not set +CONFIG_IEEE1394=m +CONFIG_IEEE1394_OHCI1394=m +CONFIG_IEEE1394_PCILYNX=m +CONFIG_IEEE1394_SBP2=m +# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set +CONFIG_IEEE1394_ETH1394_ROM_ENTRY=y +CONFIG_IEEE1394_ETH1394=m +CONFIG_IEEE1394_RAWIO=m +CONFIG_IEEE1394_VIDEO1394=m +CONFIG_IEEE1394_DV1394=m +# CONFIG_IEEE1394_VERBOSEDEBUG is not set +CONFIG_I2O=m +CONFIG_I2O_LCT_NOTIFY_ON_CHANGES=y +CONFIG_I2O_EXT_ADAPTEC=y +CONFIG_I2O_EXT_ADAPTEC_DMA64=y +CONFIG_I2O_CONFIG=m +CONFIG_I2O_CONFIG_OLD_IOCTL=y +CONFIG_I2O_BUS=m +CONFIG_I2O_BLOCK=m +CONFIG_I2O_SCSI=m +CONFIG_I2O_PROC=m +# CONFIG_MACINTOSH_DRIVERS is not set +CONFIG_NETDEVICES=y +CONFIG_IFB=m +CONFIG_DUMMY=m +CONFIG_BONDING=m +CONFIG_MACVLAN=m +CONFIG_EQUALIZER=m +CONFIG_TUN=m +CONFIG_VETH=m +# CONFIG_NET_SB1000 is not set +CONFIG_ARCNET=m +CONFIG_ARCNET_1201=m +CONFIG_ARCNET_1051=m +CONFIG_ARCNET_RAW=m +CONFIG_ARCNET_CAP=m +CONFIG_ARCNET_COM90xx=m +CONFIG_ARCNET_COM90xxIO=m +CONFIG_ARCNET_RIM_I=m +# CONFIG_ARCNET_COM20020 is not set +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +CONFIG_MARVELL_PHY=m +CONFIG_DAVICOM_PHY=m +CONFIG_QSEMI_PHY=m +CONFIG_LXT_PHY=m +CONFIG_CICADA_PHY=m +CONFIG_VITESSE_PHY=m +CONFIG_SMSC_PHY=m +CONFIG_BROADCOM_PHY=m +CONFIG_ICPLUS_PHY=m +CONFIG_REALTEK_PHY=m +CONFIG_NATIONAL_PHY=m +CONFIG_STE10XP=m +CONFIG_LSI_ET1011C_PHY=m +CONFIG_FIXED_PHY=y +CONFIG_MDIO_BITBANG=m +CONFIG_MDIO_GPIO=m +CONFIG_NET_ETHERNET=y +CONFIG_MII=m +CONFIG_HAPPYMEAL=m +CONFIG_SUNGEM=m +CONFIG_CASSINI=m +CONFIG_NET_VENDOR_3COM=y +CONFIG_VORTEX=m +CONFIG_TYPHOON=m +CONFIG_ENC28J60=m +# CONFIG_ENC28J60_WRITEVERIFY is not set +CONFIG_ETHOC=m +CONFIG_DNET=m +CONFIG_NET_TULIP=y +CONFIG_DE2104X=m +CONFIG_DE2104X_DSL=0 +CONFIG_TULIP=m +# CONFIG_TULIP_MWI is not set +# CONFIG_TULIP_MMIO is not set +CONFIG_TULIP_NAPI=y +CONFIG_TULIP_NAPI_HW_MITIGATION=y +CONFIG_DE4X5=m +CONFIG_WINBOND_840=m +CONFIG_DM9102=m +CONFIG_ULI526X=m +CONFIG_PCMCIA_XIRCOM=m +CONFIG_HP100=m +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +CONFIG_NET_PCI=y +CONFIG_PCNET32=m +CONFIG_AMD8111_ETH=m +CONFIG_ADAPTEC_STARFIRE=m +CONFIG_B44=m +CONFIG_B44_PCI_AUTOSELECT=y +CONFIG_B44_PCICORE_AUTOSELECT=y +CONFIG_B44_PCI=y +CONFIG_FORCEDETH=m +CONFIG_FORCEDETH_NAPI=y +CONFIG_E100=m +CONFIG_FEALNX=m +CONFIG_NATSEMI=m +CONFIG_NE2K_PCI=m +CONFIG_8139CP=m +CONFIG_8139TOO=m +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +CONFIG_8139TOO_8129=y +# CONFIG_8139_OLD_RX_RESET is not set +CONFIG_R6040=m +CONFIG_SIS900=m +CONFIG_EPIC100=m +CONFIG_SMSC9420=m +CONFIG_SUNDANCE=m +# CONFIG_SUNDANCE_MMIO is not set +CONFIG_TLAN=m +CONFIG_KS8842=m +CONFIG_KS8851=m +CONFIG_KS8851_MLL=m +CONFIG_VIA_RHINE=m +CONFIG_VIA_RHINE_MMIO=y +CONFIG_SC92031=m +CONFIG_NET_POCKET=y +CONFIG_ATP=m +CONFIG_DE600=m +CONFIG_DE620=m +CONFIG_ATL2=m +CONFIG_NETDEV_1000=y +CONFIG_ACENIC=m +# CONFIG_ACENIC_OMIT_TIGON_I is not set +CONFIG_DL2K=m +CONFIG_E1000=m +CONFIG_E1000E=m +CONFIG_IP1000=m +CONFIG_IGB=m +CONFIG_IGB_DCA=y +CONFIG_IGBVF=m +CONFIG_NS83820=m +CONFIG_HAMACHI=m +CONFIG_YELLOWFIN=m +CONFIG_R8169=m +CONFIG_R8169_VLAN=y +CONFIG_SIS190=m +CONFIG_SKGE=m +# CONFIG_SKGE_DEBUG is not set +CONFIG_SKY2=m +# CONFIG_SKY2_DEBUG is not set +CONFIG_VIA_VELOCITY=m +CONFIG_TIGON3=m +CONFIG_BNX2=m +CONFIG_CNIC=m +CONFIG_QLA3XXX=m +CONFIG_ATL1=m +CONFIG_ATL1E=m +CONFIG_ATL1C=m +CONFIG_JME=m +CONFIG_NETDEV_10000=y +CONFIG_MDIO=m +CONFIG_CHELSIO_T1=m +CONFIG_CHELSIO_T1_1G=y +CONFIG_CHELSIO_T3_DEPENDS=y +CONFIG_CHELSIO_T3=m +CONFIG_ENIC=m +CONFIG_IXGBE=m +CONFIG_IXGBE_DCA=y +CONFIG_IXGBE_DCB=y +CONFIG_IXGB=m +CONFIG_S2IO=m +CONFIG_VXGE=m +# CONFIG_VXGE_DEBUG_TRACE_ALL is not set +CONFIG_MYRI10GE=m +CONFIG_MYRI10GE_DCA=y +CONFIG_NETXEN_NIC=m +CONFIG_NIU=m +CONFIG_MLX4_EN=m +CONFIG_MLX4_CORE=m +CONFIG_MLX4_DEBUG=y +CONFIG_TEHUTI=m +CONFIG_BNX2X=m +CONFIG_QLGE=m +CONFIG_SFC=m +CONFIG_SFC_DRIVERLINK=y +CONFIG_SFC_RESOURCE=m +CONFIG_SFC_MTD=y +CONFIG_BE2NET=m +CONFIG_TR=m +CONFIG_IBMOL=m +CONFIG_IBMLS=m +CONFIG_3C359=m +CONFIG_TMS380TR=m +CONFIG_TMSPCI=m +CONFIG_ABYSS=m +CONFIG_WLAN=y +CONFIG_WLAN_PRE80211=y +CONFIG_STRIP=m +CONFIG_PCMCIA_WAVELAN=m +CONFIG_PCMCIA_NETWAVE=m +CONFIG_WLAN_80211=y +CONFIG_PCMCIA_RAYCS=m +CONFIG_LIBERTAS=m +CONFIG_LIBERTAS_USB=m +CONFIG_LIBERTAS_CS=m +CONFIG_LIBERTAS_SDIO=m +CONFIG_LIBERTAS_SPI=m +# CONFIG_LIBERTAS_DEBUG is not set +CONFIG_LIBERTAS_THINFIRM=m +CONFIG_LIBERTAS_THINFIRM_USB=m +CONFIG_AIRO=m +CONFIG_ATMEL=m +CONFIG_PCI_ATMEL=m +CONFIG_PCMCIA_ATMEL=m +CONFIG_AT76C50X_USB=m +CONFIG_AIRO_CS=m +CONFIG_PCMCIA_WL3501=m +CONFIG_PRISM54=m +CONFIG_USB_ZD1201=m +CONFIG_USB_NET_RNDIS_WLAN=m +CONFIG_RTL8180=m +CONFIG_RTL8187=m +CONFIG_RTL8187_LEDS=y +CONFIG_ADM8211=m +CONFIG_MAC80211_HWSIM=m +CONFIG_MWL8K=m +CONFIG_P54_COMMON=m +CONFIG_P54_USB=m +CONFIG_P54_PCI=m +CONFIG_P54_SPI=m +CONFIG_P54_LEDS=y +CONFIG_ATH_COMMON=m +CONFIG_ATH5K=m +# CONFIG_ATH5K_DEBUG is not set +CONFIG_ATH9K=m +# CONFIG_ATH9K_DEBUG is not set +CONFIG_AR9170_USB=m +CONFIG_AR9170_LEDS=y +CONFIG_IPW2100=m +CONFIG_IPW2100_MONITOR=y +CONFIG_IPW2100_DEBUG=y +CONFIG_IPW2200=m +CONFIG_IPW2200_MONITOR=y +CONFIG_IPW2200_RADIOTAP=y +CONFIG_IPW2200_PROMISCUOUS=y +CONFIG_IPW2200_QOS=y +CONFIG_IPW2200_DEBUG=y +CONFIG_LIBIPW=m +CONFIG_LIBIPW_DEBUG=y +CONFIG_IWLWIFI=m +CONFIG_IWLWIFI_LEDS=y +CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT=y +CONFIG_IWLWIFI_DEBUG=y +CONFIG_IWLWIFI_DEBUGFS=y +CONFIG_IWLAGN=m +CONFIG_IWL4965=y +CONFIG_IWL5000=y +CONFIG_IWL3945=m +CONFIG_IWL3945_SPECTRUM_MEASUREMENT=y +CONFIG_HOSTAP=m +CONFIG_HOSTAP_FIRMWARE=y +CONFIG_HOSTAP_FIRMWARE_NVRAM=y +CONFIG_HOSTAP_PLX=m +CONFIG_HOSTAP_PCI=m +CONFIG_HOSTAP_CS=m +CONFIG_B43=m +CONFIG_B43_PCI_AUTOSELECT=y +CONFIG_B43_PCICORE_AUTOSELECT=y +CONFIG_B43_PCMCIA=y +CONFIG_B43_SDIO=y +CONFIG_B43_PIO=y +CONFIG_B43_PHY_LP=y +CONFIG_B43_LEDS=y +CONFIG_B43_HWRNG=y +# CONFIG_B43_DEBUG is not set +CONFIG_B43LEGACY=m +CONFIG_B43LEGACY_PCI_AUTOSELECT=y +CONFIG_B43LEGACY_PCICORE_AUTOSELECT=y +CONFIG_B43LEGACY_LEDS=y +CONFIG_B43LEGACY_HWRNG=y +# CONFIG_B43LEGACY_DEBUG is not set +CONFIG_B43LEGACY_DMA=y +CONFIG_B43LEGACY_PIO=y +CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y +# CONFIG_B43LEGACY_DMA_MODE is not set +# CONFIG_B43LEGACY_PIO_MODE is not set +CONFIG_ZD1211RW=m +# CONFIG_ZD1211RW_DEBUG is not set +CONFIG_RT2X00=m +CONFIG_RT2400PCI=m +CONFIG_RT2500PCI=m +CONFIG_RT61PCI=m +CONFIG_RT2500USB=m +CONFIG_RT73USB=m +CONFIG_RT2800USB=m +CONFIG_RT2X00_LIB_PCI=m +CONFIG_RT2X00_LIB_USB=m +CONFIG_RT2X00_LIB=m +CONFIG_RT2X00_LIB_HT=y +CONFIG_RT2X00_LIB_FIRMWARE=y +CONFIG_RT2X00_LIB_CRYPTO=y +CONFIG_RT2X00_LIB_LEDS=y +# CONFIG_RT2X00_LIB_DEBUGFS is not set +# CONFIG_RT2X00_DEBUG is not set +CONFIG_HERMES=m +CONFIG_HERMES_CACHE_FW_ON_INIT=y +CONFIG_PLX_HERMES=m +CONFIG_TMD_HERMES=m +CONFIG_NORTEL_HERMES=m +CONFIG_PCI_HERMES=m +CONFIG_PCMCIA_HERMES=m +CONFIG_PCMCIA_SPECTRUM=m +CONFIG_WL12XX=m +CONFIG_WL1251=m +CONFIG_WL1251_SPI=m +CONFIG_WL1251_SDIO=m +CONFIG_WL1271=m +CONFIG_IWM=m +# CONFIG_IWM_DEBUG is not set + +# +# WiMAX Wireless Broadband devices +# +CONFIG_WIMAX_I2400M=m +CONFIG_WIMAX_I2400M_USB=m +CONFIG_WIMAX_I2400M_SDIO=m +CONFIG_WIMAX_I2400M_DEBUG_LEVEL=8 + +# +# USB Network Adapters +# +CONFIG_USB_CATC=m +CONFIG_USB_KAWETH=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_USBNET=m +CONFIG_USB_NET_AX8817X=m +CONFIG_USB_NET_CDCETHER=m +CONFIG_USB_NET_CDC_EEM=m +CONFIG_USB_NET_DM9601=m +CONFIG_USB_NET_SMSC95XX=m +CONFIG_USB_NET_GL620A=m +CONFIG_USB_NET_NET1080=m +CONFIG_USB_NET_PLUSB=m +CONFIG_USB_NET_MCS7830=m +CONFIG_USB_NET_RNDIS_HOST=m +CONFIG_USB_NET_CDC_SUBSET=m +CONFIG_USB_ALI_M5632=y +CONFIG_USB_AN2720=y +CONFIG_USB_BELKIN=y +CONFIG_USB_ARMLINUX=y +CONFIG_USB_EPSON2888=y +CONFIG_USB_KC2190=y +CONFIG_USB_NET_ZAURUS=m +CONFIG_USB_HSO=m +CONFIG_USB_NET_INT51X1=m +CONFIG_USB_CDC_PHONET=m +CONFIG_NET_PCMCIA=y +CONFIG_PCMCIA_3C589=m +CONFIG_PCMCIA_3C574=m +CONFIG_PCMCIA_FMVJ18X=m +CONFIG_PCMCIA_PCNET=m +CONFIG_PCMCIA_NMCLAN=m +CONFIG_PCMCIA_SMC91C92=m +CONFIG_PCMCIA_XIRC2PS=m +CONFIG_PCMCIA_AXNET=m +CONFIG_PCMCIA_IBMTR=m +CONFIG_WAN=y +CONFIG_LANMEDIA=m +CONFIG_HDLC=m +CONFIG_HDLC_RAW=m +CONFIG_HDLC_RAW_ETH=m +CONFIG_HDLC_CISCO=m +CONFIG_HDLC_FR=m +CONFIG_HDLC_PPP=m +CONFIG_HDLC_X25=m +CONFIG_PCI200SYN=m +CONFIG_WANXL=m +CONFIG_PC300TOO=m +CONFIG_FARSYNC=m +CONFIG_DSCC4=m +CONFIG_DSCC4_PCISYNC=y +CONFIG_DSCC4_PCI_RST=y +CONFIG_DLCI=m +CONFIG_DLCI_MAX=8 +# CONFIG_WAN_ROUTER_DRIVERS is not set +CONFIG_LAPBETHER=m +CONFIG_X25_ASY=m +CONFIG_SBNI=m +CONFIG_SBNI_MULTILINE=y +CONFIG_ATM_DRIVERS=y +CONFIG_ATM_DUMMY=m +CONFIG_ATM_TCP=m +CONFIG_ATM_LANAI=m +CONFIG_ATM_ENI=m +# CONFIG_ATM_ENI_DEBUG is not set +CONFIG_ATM_ENI_TUNE_BURST=y +CONFIG_ATM_ENI_BURST_TX_16W=y +CONFIG_ATM_ENI_BURST_TX_8W=y +CONFIG_ATM_ENI_BURST_TX_4W=y +CONFIG_ATM_ENI_BURST_TX_2W=y +CONFIG_ATM_ENI_BURST_RX_16W=y +CONFIG_ATM_ENI_BURST_RX_8W=y +CONFIG_ATM_ENI_BURST_RX_4W=y +CONFIG_ATM_ENI_BURST_RX_2W=y +CONFIG_ATM_FIRESTREAM=m +CONFIG_ATM_ZATM=m +# CONFIG_ATM_ZATM_DEBUG is not set +CONFIG_ATM_NICSTAR=m +CONFIG_ATM_NICSTAR_USE_SUNI=y +CONFIG_ATM_NICSTAR_USE_IDT77105=y +CONFIG_ATM_IDT77252=m +# CONFIG_ATM_IDT77252_DEBUG is not set +# CONFIG_ATM_IDT77252_RCV_ALL is not set +CONFIG_ATM_IDT77252_USE_SUNI=y +CONFIG_ATM_AMBASSADOR=m +# CONFIG_ATM_AMBASSADOR_DEBUG is not set +CONFIG_ATM_HORIZON=m +# CONFIG_ATM_HORIZON_DEBUG is not set +CONFIG_ATM_IA=m +# CONFIG_ATM_IA_DEBUG is not set +CONFIG_ATM_FORE200E=m +CONFIG_ATM_FORE200E_USE_TASKLET=y +CONFIG_ATM_FORE200E_TX_RETRY=16 +CONFIG_ATM_FORE200E_DEBUG=0 +CONFIG_ATM_HE=m +CONFIG_ATM_HE_USE_SUNI=y +CONFIG_ATM_SOLOS=m +CONFIG_IEEE802154_DRIVERS=m +CONFIG_IEEE802154_FAKEHARD=m +CONFIG_FDDI=m +CONFIG_DEFXX=m +CONFIG_DEFXX_MMIO=y +CONFIG_SKFP=m +CONFIG_HIPPI=y +CONFIG_ROADRUNNER=m +CONFIG_ROADRUNNER_LARGE_RINGS=y +CONFIG_PLIP=m +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPP_MPPE=m +CONFIG_PPPOE=m +CONFIG_PPPOATM=m +CONFIG_PPPOL2TP=m +CONFIG_SLIP=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLHC=m +CONFIG_SLIP_SMART=y +CONFIG_SLIP_MODE_SLIP6=y +CONFIG_NET_FC=y +CONFIG_NETCONSOLE=m +CONFIG_NETCONSOLE_DYNAMIC=y +CONFIG_NETPOLL=y +CONFIG_NETPOLL_TRAP=y +CONFIG_NET_POLL_CONTROLLER=y +CONFIG_ISDN=y +CONFIG_ISDN_I4L=m +CONFIG_MISDN=m +CONFIG_MISDN_DSP=m +CONFIG_MISDN_L1OIP=m + +# +# mISDN hardware drivers +# +CONFIG_MISDN_HFCPCI=m +CONFIG_MISDN_HFCMULTI=m +CONFIG_MISDN_HFCUSB=m +CONFIG_MISDN_AVMFRITZ=m +CONFIG_MISDN_SPEEDFAX=m +CONFIG_MISDN_INFINEON=m +CONFIG_MISDN_W6692=m +CONFIG_MISDN_NETJET=m +CONFIG_MISDN_IPAC=m +CONFIG_MISDN_ISAR=m +CONFIG_ISDN_PPP=y +CONFIG_ISDN_PPP_VJ=y +CONFIG_ISDN_MPP=y +CONFIG_IPPP_FILTER=y +CONFIG_ISDN_PPP_BSDCOMP=m +CONFIG_ISDN_AUDIO=y +CONFIG_ISDN_TTY_FAX=y +CONFIG_ISDN_X25=y + +# +# ISDN feature submodules +# +CONFIG_ISDN_DIVERSION=m + +# +# ISDN4Linux hardware drivers +# + +# +# Passive cards +# +CONFIG_ISDN_DRV_HISAX=m + +# +# D-channel protocol features +# +CONFIG_HISAX_EURO=y +CONFIG_DE_AOC=y +# CONFIG_HISAX_NO_SENDCOMPLETE is not set +# CONFIG_HISAX_NO_LLC is not set +# CONFIG_HISAX_NO_KEYPAD is not set +CONFIG_HISAX_1TR6=y +CONFIG_HISAX_NI1=y +CONFIG_HISAX_MAX_CARDS=8 + +# +# HiSax supported cards +# +CONFIG_HISAX_16_3=y +CONFIG_HISAX_TELESPCI=y +CONFIG_HISAX_S0BOX=y +CONFIG_HISAX_FRITZPCI=y +CONFIG_HISAX_AVM_A1_PCMCIA=y +CONFIG_HISAX_ELSA=y +CONFIG_HISAX_DIEHLDIVA=y +CONFIG_HISAX_SEDLBAUER=y +CONFIG_HISAX_NETJET=y +CONFIG_HISAX_NETJET_U=y +CONFIG_HISAX_NICCY=y +CONFIG_HISAX_BKM_A4T=y +CONFIG_HISAX_SCT_QUADRO=y +CONFIG_HISAX_GAZEL=y +CONFIG_HISAX_HFC_PCI=y +CONFIG_HISAX_W6692=y +CONFIG_HISAX_HFC_SX=y +CONFIG_HISAX_ENTERNOW_PCI=y +# CONFIG_HISAX_DEBUG is not set + +# +# HiSax PCMCIA card service modules +# +CONFIG_HISAX_SEDLBAUER_CS=m +CONFIG_HISAX_ELSA_CS=m +CONFIG_HISAX_AVM_A1_CS=m +CONFIG_HISAX_TELES_CS=m + +# +# HiSax sub driver modules +# +CONFIG_HISAX_ST5481=m +CONFIG_HISAX_HFCUSB=m +CONFIG_HISAX_HFC4S8S=m +CONFIG_HISAX_FRITZ_PCIPNP=m + +# +# Active cards +# +CONFIG_HYSDN=m +CONFIG_HYSDN_CAPI=y +CONFIG_ISDN_HDLC=m +CONFIG_ISDN_CAPI=m +CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y +CONFIG_CAPI_TRACE=y +CONFIG_ISDN_CAPI_MIDDLEWARE=y +CONFIG_ISDN_CAPI_CAPI20=m +CONFIG_ISDN_CAPI_CAPIFS_BOOL=y +CONFIG_ISDN_CAPI_CAPIFS=m +CONFIG_ISDN_CAPI_CAPIDRV=m + +# +# CAPI hardware drivers +# +CONFIG_CAPI_AVM=y +CONFIG_ISDN_DRV_AVMB1_B1PCI=m +CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y +CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m +CONFIG_ISDN_DRV_AVMB1_AVM_CS=m +CONFIG_ISDN_DRV_AVMB1_T1PCI=m +CONFIG_ISDN_DRV_AVMB1_C4=m +CONFIG_CAPI_EICON=y +CONFIG_ISDN_DIVAS=m +CONFIG_ISDN_DIVAS_BRIPCI=y +CONFIG_ISDN_DIVAS_PRIPCI=y +CONFIG_ISDN_DIVAS_DIVACAPI=m +CONFIG_ISDN_DIVAS_USERIDI=m +CONFIG_ISDN_DIVAS_MAINT=m +CONFIG_ISDN_DRV_GIGASET=m +CONFIG_GIGASET_BASE=m +CONFIG_GIGASET_M105=m +CONFIG_GIGASET_M101=m +# CONFIG_GIGASET_DEBUG is not set +CONFIG_PHONE=m +CONFIG_PHONE_IXJ=m +CONFIG_PHONE_IXJ_PCMCIA=m + +# +# Input device support +# +CONFIG_INPUT=y +CONFIG_INPUT_FF_MEMLESS=m +CONFIG_INPUT_POLLDEV=m + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +CONFIG_INPUT_JOYDEV=m +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ADP5588=m +CONFIG_KEYBOARD_ATKBD=y +CONFIG_QT2160=m +# CONFIG_KEYBOARD_LKKBD is not set +CONFIG_KEYBOARD_GPIO=m +CONFIG_KEYBOARD_MATRIX=m +CONFIG_KEYBOARD_LM8323=m +CONFIG_KEYBOARD_MAX7359=m +CONFIG_KEYBOARD_NEWTON=m +CONFIG_KEYBOARD_OPENCORES=m +# CONFIG_KEYBOARD_STOWAWAY is not set +CONFIG_KEYBOARD_SUNKBD=m +CONFIG_KEYBOARD_XTKBD=m +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_PS2_ALPS=y +CONFIG_MOUSE_PS2_LOGIPS2PP=y +CONFIG_MOUSE_PS2_SYNAPTICS=y +CONFIG_MOUSE_PS2_LIFEBOOK=y +CONFIG_MOUSE_PS2_TRACKPOINT=y +CONFIG_MOUSE_PS2_ELANTECH=y +CONFIG_MOUSE_PS2_SENTELIC=y +CONFIG_MOUSE_PS2_TOUCHKIT=y +CONFIG_MOUSE_PS2_OLPC=y +CONFIG_MOUSE_SERIAL=m +CONFIG_MOUSE_APPLETOUCH=m +CONFIG_MOUSE_BCM5974=m +CONFIG_MOUSE_VSXXXAA=m +CONFIG_MOUSE_GPIO=m +CONFIG_MOUSE_SYNAPTICS_I2C=m +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_ANALOG=m +CONFIG_JOYSTICK_A3D=m +CONFIG_JOYSTICK_ADI=m +CONFIG_JOYSTICK_COBRA=m +CONFIG_JOYSTICK_GF2K=m +CONFIG_JOYSTICK_GRIP=m +CONFIG_JOYSTICK_GRIP_MP=m +CONFIG_JOYSTICK_GUILLEMOT=m +CONFIG_JOYSTICK_INTERACT=m +CONFIG_JOYSTICK_SIDEWINDER=m +CONFIG_JOYSTICK_TMDC=m +CONFIG_JOYSTICK_IFORCE=m +CONFIG_JOYSTICK_IFORCE_USB=y +CONFIG_JOYSTICK_IFORCE_232=y +CONFIG_JOYSTICK_WARRIOR=m +CONFIG_JOYSTICK_MAGELLAN=m +CONFIG_JOYSTICK_SPACEORB=m +CONFIG_JOYSTICK_SPACEBALL=m +CONFIG_JOYSTICK_STINGER=m +CONFIG_JOYSTICK_TWIDJOY=m +CONFIG_JOYSTICK_ZHENHUA=m +CONFIG_JOYSTICK_DB9=m +CONFIG_JOYSTICK_GAMECON=m +CONFIG_JOYSTICK_TURBOGRAFX=m +CONFIG_JOYSTICK_JOYDUMP=m +CONFIG_JOYSTICK_XPAD=m +CONFIG_JOYSTICK_XPAD_FF=y +CONFIG_JOYSTICK_XPAD_LEDS=y +CONFIG_INPUT_TABLET=y +CONFIG_TABLET_USB_ACECAD=m +CONFIG_TABLET_USB_AIPTEK=m +CONFIG_TABLET_USB_GTCO=m +CONFIG_TABLET_USB_KBTAB=m +CONFIG_TABLET_USB_WACOM=m +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_ADS7846=m +CONFIG_TOUCHSCREEN_AD7877=m +CONFIG_TOUCHSCREEN_AD7879_I2C=m +CONFIG_TOUCHSCREEN_AD7879=m +CONFIG_TOUCHSCREEN_EETI=m +CONFIG_TOUCHSCREEN_FUJITSU=m +CONFIG_TOUCHSCREEN_GUNZE=m +CONFIG_TOUCHSCREEN_ELO=m +CONFIG_TOUCHSCREEN_WACOM_W8001=m +CONFIG_TOUCHSCREEN_MCS5000=m +CONFIG_TOUCHSCREEN_MTOUCH=m +CONFIG_TOUCHSCREEN_INEXIO=m +CONFIG_TOUCHSCREEN_MK712=m +CONFIG_TOUCHSCREEN_PENMOUNT=m +CONFIG_TOUCHSCREEN_TOUCHRIGHT=m +CONFIG_TOUCHSCREEN_TOUCHWIN=m +CONFIG_TOUCHSCREEN_UCB1400=m +CONFIG_TOUCHSCREEN_WM97XX=m +CONFIG_TOUCHSCREEN_WM9705=y +CONFIG_TOUCHSCREEN_WM9712=y +CONFIG_TOUCHSCREEN_WM9713=y +CONFIG_TOUCHSCREEN_USB_COMPOSITE=m +CONFIG_TOUCHSCREEN_USB_EGALAX=y +CONFIG_TOUCHSCREEN_USB_PANJIT=y +CONFIG_TOUCHSCREEN_USB_3M=y +CONFIG_TOUCHSCREEN_USB_ITM=y +CONFIG_TOUCHSCREEN_USB_ETURBO=y +CONFIG_TOUCHSCREEN_USB_GUNZE=y +CONFIG_TOUCHSCREEN_USB_DMC_TSC10=y +CONFIG_TOUCHSCREEN_USB_IRTOUCH=y +CONFIG_TOUCHSCREEN_USB_IDEALTEK=y +CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH=y +CONFIG_TOUCHSCREEN_USB_GOTOP=y +CONFIG_TOUCHSCREEN_USB_JASTEC=y +CONFIG_TOUCHSCREEN_USB_E2I=y +CONFIG_TOUCHSCREEN_TOUCHIT213=m +CONFIG_TOUCHSCREEN_TSC2007=m +CONFIG_TOUCHSCREEN_PCAP=m +CONFIG_INPUT_MISC=y +CONFIG_INPUT_PCSPKR=m +CONFIG_INPUT_APANEL=m +CONFIG_INPUT_WISTRON_BTNS=m +CONFIG_INPUT_ATLAS_BTNS=m +CONFIG_INPUT_ATI_REMOTE=m +CONFIG_INPUT_ATI_REMOTE2=m +CONFIG_INPUT_KEYSPAN_REMOTE=m +CONFIG_INPUT_POWERMATE=m +CONFIG_INPUT_YEALINK=m +CONFIG_INPUT_CM109=m +CONFIG_INPUT_UINPUT=m +CONFIG_INPUT_WINBOND_CIR=m +CONFIG_INPUT_GPIO_ROTARY_ENCODER=m +CONFIG_INPUT_PCAP=m + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=m +CONFIG_SERIO_CT82C710=m +CONFIG_SERIO_PARKBD=m +CONFIG_SERIO_PCIPS2=m +CONFIG_SERIO_LIBPS2=y +CONFIG_SERIO_RAW=m +CONFIG_GAMEPORT=m +CONFIG_GAMEPORT_NS558=m +CONFIG_GAMEPORT_L4=m +CONFIG_GAMEPORT_EMU10K1=m +CONFIG_GAMEPORT_FM801=m + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_DEVKMEM=y +CONFIG_SERIAL_NONSTANDARD=y +CONFIG_COMPUTONE=m +CONFIG_ROCKETPORT=m +CONFIG_CYCLADES=m +# CONFIG_CYZ_INTR is not set +CONFIG_DIGIEPCA=m +CONFIG_MOXA_INTELLIO=m +CONFIG_MOXA_SMARTIO=m +CONFIG_ISI=m +CONFIG_SYNCLINK=m +CONFIG_SYNCLINKMP=m +CONFIG_SYNCLINK_GT=m +CONFIG_N_HDLC=m +CONFIG_RISCOM8=m +CONFIG_SPECIALIX=m +CONFIG_STALDRV=y +CONFIG_STALLION=m +CONFIG_ISTALLION=m +CONFIG_NOZOMI=m + +# +# Serial drivers +# +CONFIG_SERIAL_8250=m +CONFIG_FIX_EARLYCON_MEM=y +CONFIG_SERIAL_8250_PCI=m +CONFIG_SERIAL_8250_PNP=m +CONFIG_SERIAL_8250_CS=m +CONFIG_SERIAL_8250_NR_UARTS=16 +CONFIG_SERIAL_8250_RUNTIME_UARTS=8 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_MAX3100 is not set +CONFIG_SERIAL_CORE=m +CONFIG_SERIAL_JSM=m +CONFIG_UNIX98_PTYS=y +CONFIG_DEVPTS_MULTIPLE_INSTANCES=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=0 +CONFIG_PRINTER=m +# CONFIG_LP_CONSOLE is not set +CONFIG_PPDEV=m +CONFIG_IPMI_HANDLER=m +CONFIG_IPMI_PANIC_EVENT=y +# CONFIG_IPMI_PANIC_STRING is not set +CONFIG_IPMI_DEVICE_INTERFACE=m +CONFIG_IPMI_SI=m +CONFIG_IPMI_WATCHDOG=m +CONFIG_IPMI_POWEROFF=m +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_TIMERIOMEM=m +CONFIG_HW_RANDOM_INTEL=m +CONFIG_HW_RANDOM_AMD=m +CONFIG_HW_RANDOM_GEODE=m +CONFIG_HW_RANDOM_VIA=m +CONFIG_NVRAM=y +CONFIG_R3964=m +CONFIG_APPLICOM=m +CONFIG_SONYPI=m + +# +# PCMCIA character devices +# +CONFIG_SYNCLINK_CS=m +CONFIG_CARDMAN_4000=m +CONFIG_CARDMAN_4040=m +CONFIG_IPWIRELESS=m +CONFIG_MWAVE=m +CONFIG_SCx200_GPIO=m +CONFIG_PC8736x_GPIO=m +CONFIG_NSC_GPIO=m +CONFIG_CS5535_GPIO=m +CONFIG_RAW_DRIVER=m +CONFIG_MAX_RAW_DEVS=4096 +CONFIG_HANGCHECK_TIMER=m +CONFIG_TCG_TPM=m +CONFIG_TCG_TIS=m +CONFIG_TCG_NSC=m +CONFIG_TCG_ATMEL=m +CONFIG_TCG_INFINEON=m +CONFIG_TCG_XEN=m +CONFIG_TELCLOCK=m +CONFIG_DEVPORT=y +CONFIG_I2C=m +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_COMPAT=y +CONFIG_I2C_CHARDEV=m +CONFIG_I2C_HELPER_AUTO=y +CONFIG_I2C_ALGOBIT=m +CONFIG_I2C_ALGOPCA=m + +# +# I2C Hardware Bus support +# + +# +# PC SMBus host controller drivers +# +CONFIG_I2C_ALI1535=m +CONFIG_I2C_ALI1563=m +CONFIG_I2C_ALI15X3=m +CONFIG_I2C_AMD756=m +CONFIG_I2C_AMD756_S4882=m +CONFIG_I2C_AMD8111=m +CONFIG_I2C_I801=m +CONFIG_I2C_ISCH=m +CONFIG_I2C_PIIX4=m +CONFIG_I2C_NFORCE2=m +CONFIG_I2C_NFORCE2_S4985=m +CONFIG_I2C_SIS5595=m +CONFIG_I2C_SIS630=m +CONFIG_I2C_SIS96X=m +CONFIG_I2C_VIA=m +CONFIG_I2C_VIAPRO=m + +# +# ACPI drivers +# +CONFIG_I2C_SCMI=m + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +CONFIG_I2C_GPIO=m +CONFIG_I2C_OCORES=m +# CONFIG_I2C_SIMTEC is not set + +# +# External I2C/SMBus adapter drivers +# +CONFIG_I2C_PARPORT=m +CONFIG_I2C_PARPORT_LIGHT=m +CONFIG_I2C_TAOS_EVM=m +CONFIG_I2C_TINY_USB=m + +# +# Graphics adapter I2C/DDC channel drivers +# +# CONFIG_I2C_VOODOO3 is not set + +# +# Other I2C/SMBus bus drivers +# +CONFIG_I2C_PCA_PLATFORM=m +CONFIG_I2C_STUB=m +CONFIG_SCx200_I2C=m +CONFIG_SCx200_I2C_SCL=12 +CONFIG_SCx200_I2C_SDA=13 +CONFIG_SCx200_ACB=m + +# +# Miscellaneous I2C Chip support +# +CONFIG_DS1682=m +CONFIG_SENSORS_TSL2550=m +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +CONFIG_SPI_BITBANG=m +CONFIG_SPI_BUTTERFLY=m +CONFIG_SPI_GPIO=m +CONFIG_SPI_LM70_LLP=m + +# +# SPI Protocol Masters +# +CONFIG_SPI_SPIDEV=m +CONFIG_SPI_TLE62X0=m + +# +# PPS support +# +CONFIG_PPS=m +# CONFIG_PPS_DEBUG is not set +CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y +CONFIG_GPIOLIB=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO expanders: +# + +# +# I2C GPIO expanders: +# +CONFIG_GPIO_MAX732X=m +CONFIG_GPIO_PCA953X=m +CONFIG_GPIO_PCF857X=m + +# +# PCI GPIO expanders: +# +CONFIG_GPIO_LANGWELL=y + +# +# SPI GPIO expanders: +# +CONFIG_GPIO_MAX7301=m +CONFIG_GPIO_MCP23S08=m +CONFIG_GPIO_MC33880=m + +# +# AC97 GPIO expanders: +# +CONFIG_GPIO_UCB1400=y +CONFIG_W1=m +CONFIG_W1_CON=y + +# +# 1-wire Bus Masters +# +CONFIG_W1_MASTER_MATROX=m +CONFIG_W1_MASTER_DS2490=m +CONFIG_W1_MASTER_DS2482=m +CONFIG_W1_MASTER_GPIO=m + +# +# 1-wire Slaves +# +CONFIG_W1_SLAVE_THERM=m +CONFIG_W1_SLAVE_SMEM=m +CONFIG_W1_SLAVE_DS2431=m +CONFIG_W1_SLAVE_DS2433=m +CONFIG_W1_SLAVE_DS2433_CRC=y +CONFIG_W1_SLAVE_DS2760=m +CONFIG_W1_SLAVE_BQ27000=m +CONFIG_POWER_SUPPLY=y +# CONFIG_POWER_SUPPLY_DEBUG is not set +CONFIG_PDA_POWER=m +CONFIG_BATTERY_DS2760=m +CONFIG_BATTERY_DS2782=m +CONFIG_BATTERY_OLPC=m +CONFIG_BATTERY_BQ27x00=m +CONFIG_BATTERY_MAX17040=m +CONFIG_HWMON=m +CONFIG_HWMON_VID=m +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Native drivers +# +CONFIG_SENSORS_ABITUGURU=m +CONFIG_SENSORS_ABITUGURU3=m +CONFIG_SENSORS_AD7414=m +CONFIG_SENSORS_AD7418=m +CONFIG_SENSORS_ADCXX=m +CONFIG_SENSORS_ADM1021=m +CONFIG_SENSORS_ADM1025=m +CONFIG_SENSORS_ADM1026=m +CONFIG_SENSORS_ADM1029=m +CONFIG_SENSORS_ADM1031=m +CONFIG_SENSORS_ADM9240=m +CONFIG_SENSORS_ADT7462=m +CONFIG_SENSORS_ADT7470=m +CONFIG_SENSORS_ADT7473=m +CONFIG_SENSORS_ADT7475=m +CONFIG_SENSORS_K8TEMP=m +CONFIG_SENSORS_ASB100=m +CONFIG_SENSORS_ATXP1=m +CONFIG_SENSORS_DS1621=m +CONFIG_SENSORS_I5K_AMB=m +CONFIG_SENSORS_F71805F=m +CONFIG_SENSORS_F71882FG=m +CONFIG_SENSORS_F75375S=m +CONFIG_SENSORS_FSCHMD=m +CONFIG_SENSORS_G760A=m +CONFIG_SENSORS_GL518SM=m +CONFIG_SENSORS_GL520SM=m +CONFIG_SENSORS_CORETEMP=m +CONFIG_SENSORS_IBMAEM=m +CONFIG_SENSORS_IBMPEX=m +CONFIG_SENSORS_IT87=m +CONFIG_SENSORS_LM63=m +CONFIG_SENSORS_LM70=m +CONFIG_SENSORS_LM75=m +CONFIG_SENSORS_LM77=m +CONFIG_SENSORS_LM78=m +CONFIG_SENSORS_LM80=m +CONFIG_SENSORS_LM83=m +CONFIG_SENSORS_LM85=m +CONFIG_SENSORS_LM87=m +CONFIG_SENSORS_LM90=m +CONFIG_SENSORS_LM92=m +CONFIG_SENSORS_LM93=m +CONFIG_SENSORS_LTC4215=m +CONFIG_SENSORS_LTC4245=m +CONFIG_SENSORS_LM95241=m +CONFIG_SENSORS_MAX1111=m +CONFIG_SENSORS_MAX1619=m +CONFIG_SENSORS_MAX6650=m +CONFIG_SENSORS_PC87360=m +CONFIG_SENSORS_PC87427=m +CONFIG_SENSORS_PCF8591=m +CONFIG_SENSORS_SHT15=m +CONFIG_SENSORS_SIS5595=m +CONFIG_SENSORS_DME1737=m +CONFIG_SENSORS_SMSC47M1=m +CONFIG_SENSORS_SMSC47M192=m +CONFIG_SENSORS_SMSC47B397=m +CONFIG_SENSORS_ADS7828=m +CONFIG_SENSORS_THMC50=m +CONFIG_SENSORS_TMP401=m +CONFIG_SENSORS_TMP421=m +CONFIG_SENSORS_VIA686A=m +CONFIG_SENSORS_VT1211=m +CONFIG_SENSORS_VT8231=m +CONFIG_SENSORS_W83781D=m +CONFIG_SENSORS_W83791D=m +CONFIG_SENSORS_W83792D=m +CONFIG_SENSORS_W83793=m +CONFIG_SENSORS_W83L785TS=m +CONFIG_SENSORS_W83L786NG=m +CONFIG_SENSORS_W83627HF=m +CONFIG_SENSORS_W83627EHF=m +CONFIG_SENSORS_HDAPS=m +CONFIG_SENSORS_APPLESMC=m + +# +# ACPI drivers +# +CONFIG_SENSORS_ATK0110=m +CONFIG_SENSORS_LIS3LV02D=m +CONFIG_THERMAL=m +CONFIG_THERMAL_HWMON=y +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +CONFIG_SOFT_WATCHDOG=m +CONFIG_ACQUIRE_WDT=m +CONFIG_ADVANTECH_WDT=m +CONFIG_ALIM1535_WDT=m +CONFIG_ALIM7101_WDT=m +CONFIG_SC520_WDT=m +CONFIG_SBC_FITPC2_WATCHDOG=m +CONFIG_EUROTECH_WDT=m +CONFIG_IB700_WDT=m +CONFIG_IBMASR=m +CONFIG_WAFER_WDT=m +CONFIG_I6300ESB_WDT=m +CONFIG_ITCO_WDT=m +CONFIG_ITCO_VENDOR_SUPPORT=y +CONFIG_IT8712F_WDT=m +CONFIG_IT87_WDT=m +CONFIG_HP_WATCHDOG=m +CONFIG_SC1200_WDT=m +CONFIG_SCx200_WDT=m +CONFIG_PC87413_WDT=m +CONFIG_60XX_WDT=m +CONFIG_SBC8360_WDT=m +CONFIG_SBC7240_WDT=m +CONFIG_CPU5_WDT=m +CONFIG_SMSC_SCH311X_WDT=m +CONFIG_SMSC37B787_WDT=m +CONFIG_W83627HF_WDT=m +CONFIG_W83697HF_WDT=m +CONFIG_W83697UG_WDT=m +CONFIG_W83877F_WDT=m +CONFIG_W83977F_WDT=m +CONFIG_MACHZ_WDT=m +CONFIG_SBC_EPX_C3_WATCHDOG=m + +# +# PCI-based Watchdog Cards +# +CONFIG_PCIPCWATCHDOG=m +CONFIG_WDTPCI=m + +# +# USB-based Watchdog Cards +# +CONFIG_USBPCWATCHDOG=m +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +CONFIG_SSB=m +CONFIG_SSB_SPROM=y +CONFIG_SSB_BLOCKIO=y +CONFIG_SSB_PCIHOST_POSSIBLE=y +CONFIG_SSB_PCIHOST=y +CONFIG_SSB_B43_PCI_BRIDGE=y +CONFIG_SSB_PCMCIAHOST_POSSIBLE=y +CONFIG_SSB_PCMCIAHOST=y +CONFIG_SSB_SDIOHOST_POSSIBLE=y +CONFIG_SSB_SDIOHOST=y +# CONFIG_SSB_DEBUG is not set +CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y +CONFIG_SSB_DRIVER_PCICORE=y + +# +# Multifunction device drivers +# +CONFIG_MFD_CORE=m +CONFIG_MFD_SM501=m +CONFIG_MFD_SM501_GPIO=y +CONFIG_HTC_PASIC3=m +CONFIG_UCB1400_CORE=m +CONFIG_TPS65010=m +# CONFIG_MFD_TMIO is not set +CONFIG_MFD_WM8400=m +# CONFIG_MFD_WM831X is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_PCF50633 is not set +CONFIG_MFD_MC13783=m +CONFIG_AB3100_CORE=m +CONFIG_AB3100_OTP=m +CONFIG_EZX_PCAP=y +CONFIG_REGULATOR=y +# CONFIG_REGULATOR_DEBUG is not set +# CONFIG_REGULATOR_FIXED_VOLTAGE is not set +CONFIG_REGULATOR_VIRTUAL_CONSUMER=m +CONFIG_REGULATOR_USERSPACE_CONSUMER=m +CONFIG_REGULATOR_BQ24022=m +CONFIG_REGULATOR_MAX1586=m +CONFIG_REGULATOR_WM8400=m +CONFIG_REGULATOR_LP3971=m +CONFIG_REGULATOR_PCAP=m +CONFIG_REGULATOR_MC13783=m +CONFIG_REGULATOR_AB3100=m +CONFIG_REGULATOR_TPS65023=m +CONFIG_REGULATOR_TPS6507X=m +CONFIG_MEDIA_SUPPORT=m + +# +# Multimedia core support +# +CONFIG_VIDEO_DEV=m +CONFIG_VIDEO_V4L2_COMMON=m +CONFIG_VIDEO_ALLOW_V4L1=y +CONFIG_VIDEO_V4L1_COMPAT=y +CONFIG_DVB_CORE=m +CONFIG_VIDEO_MEDIA=m + +# +# Multimedia drivers +# +CONFIG_VIDEO_SAA7146=m +CONFIG_VIDEO_SAA7146_VV=m +CONFIG_MEDIA_ATTACH=y +CONFIG_MEDIA_TUNER=m +# CONFIG_MEDIA_TUNER_CUSTOMISE is not set +CONFIG_MEDIA_TUNER_SIMPLE=m +CONFIG_MEDIA_TUNER_TDA8290=m +CONFIG_MEDIA_TUNER_TDA827X=m +CONFIG_MEDIA_TUNER_TDA18271=m +CONFIG_MEDIA_TUNER_TDA9887=m +CONFIG_MEDIA_TUNER_TEA5761=m +CONFIG_MEDIA_TUNER_TEA5767=m +CONFIG_MEDIA_TUNER_MT20XX=m +CONFIG_MEDIA_TUNER_MT2060=m +CONFIG_MEDIA_TUNER_MT2266=m +CONFIG_MEDIA_TUNER_MT2131=m +CONFIG_MEDIA_TUNER_QT1010=m +CONFIG_MEDIA_TUNER_XC2028=m +CONFIG_MEDIA_TUNER_XC5000=m +CONFIG_MEDIA_TUNER_MXL5005S=m +CONFIG_MEDIA_TUNER_MXL5007T=m +CONFIG_MEDIA_TUNER_MC44S803=m +CONFIG_VIDEO_V4L2=m +CONFIG_VIDEO_V4L1=m +CONFIG_VIDEOBUF_GEN=m +CONFIG_VIDEOBUF_DMA_SG=m +CONFIG_VIDEOBUF_VMALLOC=m +CONFIG_VIDEOBUF_DVB=m +CONFIG_VIDEO_BTCX=m +CONFIG_VIDEO_IR=m +CONFIG_VIDEO_TVEEPROM=m +CONFIG_VIDEO_TUNER=m +CONFIG_VIDEO_CAPTURE_DRIVERS=y +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set +CONFIG_VIDEO_HELPER_CHIPS_AUTO=y +CONFIG_VIDEO_IR_I2C=m +CONFIG_VIDEO_TVAUDIO=m +CONFIG_VIDEO_TDA7432=m +CONFIG_VIDEO_TDA9840=m +CONFIG_VIDEO_TEA6415C=m +CONFIG_VIDEO_TEA6420=m +CONFIG_VIDEO_MSP3400=m +CONFIG_VIDEO_CS5345=m +CONFIG_VIDEO_CS53L32A=m +CONFIG_VIDEO_M52790=m +CONFIG_VIDEO_WM8775=m +CONFIG_VIDEO_WM8739=m +CONFIG_VIDEO_VP27SMPX=m +CONFIG_VIDEO_SAA6588=m +CONFIG_VIDEO_BT819=m +CONFIG_VIDEO_BT856=m +CONFIG_VIDEO_BT866=m +CONFIG_VIDEO_KS0127=m +CONFIG_VIDEO_OV7670=m +CONFIG_VIDEO_MT9V011=m +CONFIG_VIDEO_SAA7110=m +CONFIG_VIDEO_SAA711X=m +CONFIG_VIDEO_SAA717X=m +CONFIG_VIDEO_TVP5150=m +CONFIG_VIDEO_VPX3220=m +CONFIG_VIDEO_CX25840=m +CONFIG_VIDEO_CX2341X=m +CONFIG_VIDEO_SAA7127=m +CONFIG_VIDEO_SAA7185=m +CONFIG_VIDEO_ADV7170=m +CONFIG_VIDEO_ADV7175=m +CONFIG_VIDEO_UPD64031A=m +CONFIG_VIDEO_UPD64083=m +CONFIG_VIDEO_VIVI=m +CONFIG_VIDEO_BT848=m +CONFIG_VIDEO_BT848_DVB=y +CONFIG_VIDEO_BWQCAM=m +CONFIG_VIDEO_CQCAM=m +CONFIG_VIDEO_W9966=m +CONFIG_VIDEO_CPIA=m +CONFIG_VIDEO_CPIA_PP=m +CONFIG_VIDEO_CPIA_USB=m +CONFIG_VIDEO_CPIA2=m +CONFIG_VIDEO_SAA5246A=m +CONFIG_VIDEO_SAA5249=m +CONFIG_VIDEO_STRADIS=m +CONFIG_VIDEO_ZORAN=m +CONFIG_VIDEO_ZORAN_DC30=m +CONFIG_VIDEO_ZORAN_ZR36060=m +CONFIG_VIDEO_ZORAN_BUZ=m +CONFIG_VIDEO_ZORAN_DC10=m +CONFIG_VIDEO_ZORAN_LML33=m +CONFIG_VIDEO_ZORAN_LML33R10=m +CONFIG_VIDEO_ZORAN_AVS6EYES=m +CONFIG_VIDEO_MEYE=m +CONFIG_VIDEO_SAA7134=m +CONFIG_VIDEO_SAA7134_ALSA=m +CONFIG_VIDEO_SAA7134_DVB=m +CONFIG_VIDEO_MXB=m +CONFIG_VIDEO_HEXIUM_ORION=m +CONFIG_VIDEO_HEXIUM_GEMINI=m +CONFIG_VIDEO_CX88=m +CONFIG_VIDEO_CX88_ALSA=m +CONFIG_VIDEO_CX88_BLACKBIRD=m +CONFIG_VIDEO_CX88_DVB=m +CONFIG_VIDEO_CX88_MPEG=m +CONFIG_VIDEO_CX88_VP3054=m +CONFIG_VIDEO_CX23885=m +CONFIG_VIDEO_AU0828=m +CONFIG_VIDEO_IVTV=m +CONFIG_VIDEO_FB_IVTV=m +CONFIG_VIDEO_CX18=m +CONFIG_VIDEO_SAA7164=m +CONFIG_VIDEO_CAFE_CCIC=m +CONFIG_SOC_CAMERA=m +CONFIG_SOC_CAMERA_MT9M001=m +CONFIG_SOC_CAMERA_MT9M111=m +CONFIG_SOC_CAMERA_MT9T031=m +CONFIG_SOC_CAMERA_MT9V022=m +CONFIG_SOC_CAMERA_TW9910=m +CONFIG_SOC_CAMERA_PLATFORM=m +CONFIG_SOC_CAMERA_OV772X=m +CONFIG_V4L_USB_DRIVERS=y +CONFIG_USB_VIDEO_CLASS=m +CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y +CONFIG_USB_GSPCA=m +CONFIG_USB_M5602=m +CONFIG_USB_STV06XX=m +CONFIG_USB_GL860=m +CONFIG_USB_GSPCA_CONEX=m +CONFIG_USB_GSPCA_ETOMS=m +CONFIG_USB_GSPCA_FINEPIX=m +CONFIG_USB_GSPCA_JEILINJ=m +CONFIG_USB_GSPCA_MARS=m +CONFIG_USB_GSPCA_MR97310A=m +CONFIG_USB_GSPCA_OV519=m +CONFIG_USB_GSPCA_OV534=m +CONFIG_USB_GSPCA_PAC207=m +CONFIG_USB_GSPCA_PAC7311=m +CONFIG_USB_GSPCA_SN9C20X=m +CONFIG_USB_GSPCA_SN9C20X_EVDEV=y +CONFIG_USB_GSPCA_SONIXB=m +CONFIG_USB_GSPCA_SONIXJ=m +CONFIG_USB_GSPCA_SPCA500=m +CONFIG_USB_GSPCA_SPCA501=m +CONFIG_USB_GSPCA_SPCA505=m +CONFIG_USB_GSPCA_SPCA506=m +CONFIG_USB_GSPCA_SPCA508=m +CONFIG_USB_GSPCA_SPCA561=m +CONFIG_USB_GSPCA_SQ905=m +CONFIG_USB_GSPCA_SQ905C=m +CONFIG_USB_GSPCA_STK014=m +CONFIG_USB_GSPCA_SUNPLUS=m +CONFIG_USB_GSPCA_T613=m +CONFIG_USB_GSPCA_TV8532=m +CONFIG_USB_GSPCA_VC032X=m +CONFIG_USB_GSPCA_ZC3XX=m +CONFIG_VIDEO_PVRUSB2=m +CONFIG_VIDEO_PVRUSB2_SYSFS=y +CONFIG_VIDEO_PVRUSB2_DVB=y +# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set +CONFIG_VIDEO_HDPVR=m +CONFIG_VIDEO_EM28XX=m +CONFIG_VIDEO_EM28XX_ALSA=m +CONFIG_VIDEO_EM28XX_DVB=m +CONFIG_VIDEO_CX231XX=m +CONFIG_VIDEO_CX231XX_ALSA=m +CONFIG_VIDEO_CX231XX_DVB=m +CONFIG_VIDEO_USBVISION=m +CONFIG_VIDEO_USBVIDEO=m +CONFIG_USB_VICAM=m +CONFIG_USB_IBMCAM=m +CONFIG_USB_KONICAWC=m +CONFIG_USB_QUICKCAM_MESSENGER=m +CONFIG_USB_ET61X251=m +CONFIG_VIDEO_OVCAMCHIP=m +CONFIG_USB_W9968CF=m +CONFIG_USB_OV511=m +CONFIG_USB_SE401=m +CONFIG_USB_SN9C102=m +CONFIG_USB_STV680=m +CONFIG_USB_ZC0301=m +CONFIG_USB_PWC=m +# CONFIG_USB_PWC_DEBUG is not set +CONFIG_USB_PWC_INPUT_EVDEV=y +CONFIG_USB_ZR364XX=m +CONFIG_USB_STKWEBCAM=m +CONFIG_USB_S2255=m +CONFIG_RADIO_ADAPTERS=y +CONFIG_RADIO_GEMTEK_PCI=m +CONFIG_RADIO_MAXIRADIO=m +CONFIG_RADIO_MAESTRO=m +CONFIG_I2C_SI4713=m +CONFIG_RADIO_SI4713=m +CONFIG_USB_DSBR=m +CONFIG_RADIO_SI470X=y +CONFIG_USB_SI470X=m +CONFIG_I2C_SI470X=m +CONFIG_USB_MR800=m +CONFIG_RADIO_TEA5764=m +CONFIG_DVB_MAX_ADAPTERS=8 +CONFIG_DVB_DYNAMIC_MINORS=y +CONFIG_DVB_CAPTURE_DRIVERS=y + +# +# Supported SAA7146 based PCI Adapters +# +CONFIG_TTPCI_EEPROM=m +CONFIG_DVB_AV7110=m +CONFIG_DVB_AV7110_OSD=y +CONFIG_DVB_BUDGET_CORE=m +CONFIG_DVB_BUDGET=m +CONFIG_DVB_BUDGET_CI=m +CONFIG_DVB_BUDGET_AV=m +CONFIG_DVB_BUDGET_PATCH=m + +# +# Supported USB Adapters +# +CONFIG_DVB_USB=m +# CONFIG_DVB_USB_DEBUG is not set +CONFIG_DVB_USB_A800=m +CONFIG_DVB_USB_DIBUSB_MB=m +# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set +CONFIG_DVB_USB_DIBUSB_MC=m +CONFIG_DVB_USB_DIB0700=m +CONFIG_DVB_USB_UMT_010=m +CONFIG_DVB_USB_CXUSB=m +CONFIG_DVB_USB_M920X=m +CONFIG_DVB_USB_GL861=m +CONFIG_DVB_USB_AU6610=m +CONFIG_DVB_USB_DIGITV=m +CONFIG_DVB_USB_VP7045=m +CONFIG_DVB_USB_VP702X=m +CONFIG_DVB_USB_GP8PSK=m +CONFIG_DVB_USB_NOVA_T_USB2=m +CONFIG_DVB_USB_TTUSB2=m +CONFIG_DVB_USB_DTT200U=m +CONFIG_DVB_USB_OPERA1=m +CONFIG_DVB_USB_AF9005=m +CONFIG_DVB_USB_AF9005_REMOTE=m +CONFIG_DVB_USB_DW2102=m +CONFIG_DVB_USB_CINERGY_T2=m +CONFIG_DVB_USB_ANYSEE=m +CONFIG_DVB_USB_DTV5100=m +CONFIG_DVB_USB_AF9015=m +CONFIG_DVB_USB_CE6230=m +CONFIG_DVB_USB_FRIIO=m +CONFIG_DVB_TTUSB_BUDGET=m +CONFIG_DVB_TTUSB_DEC=m +CONFIG_SMS_SIANO_MDTV=m + +# +# Siano module components +# +CONFIG_SMS_USB_DRV=m +CONFIG_SMS_SDIO_DRV=m + +# +# Supported FlexCopII (B2C2) Adapters +# +CONFIG_DVB_B2C2_FLEXCOP=m +CONFIG_DVB_B2C2_FLEXCOP_PCI=m +CONFIG_DVB_B2C2_FLEXCOP_USB=m +# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set + +# +# Supported BT878 Adapters +# +CONFIG_DVB_BT8XX=m + +# +# Supported Pluto2 Adapters +# +CONFIG_DVB_PLUTO2=m + +# +# Supported SDMC DM1105 Adapters +# +CONFIG_DVB_DM1105=m + +# +# Supported FireWire (IEEE 1394) Adapters +# +CONFIG_DVB_FIREDTV=m +CONFIG_DVB_FIREDTV_IEEE1394=y +CONFIG_DVB_FIREDTV_INPUT=y + +# +# Supported Earthsoft PT1 Adapters +# +CONFIG_DVB_PT1=m + +# +# Supported DVB Frontends +# +CONFIG_DVB_FE_CUSTOMISE=y + +# +# Customise DVB Frontends +# + +# +# Multistandard (satellite) frontends +# +CONFIG_DVB_STB0899=m +CONFIG_DVB_STB6100=m +# CONFIG_DVB_STV090x is not set +# CONFIG_DVB_STV6110x is not set + +# +# DVB-S (satellite) frontends +# +CONFIG_DVB_CX24110=m +CONFIG_DVB_CX24123=m +CONFIG_DVB_MT312=m +CONFIG_DVB_ZL10036=m +CONFIG_DVB_ZL10039=m +CONFIG_DVB_S5H1420=m +CONFIG_DVB_STV0288=m +CONFIG_DVB_STB6000=m +CONFIG_DVB_STV0299=m +CONFIG_DVB_STV6110=m +CONFIG_DVB_STV0900=m +CONFIG_DVB_TDA8083=m +CONFIG_DVB_TDA10086=m +CONFIG_DVB_TDA8261=m +CONFIG_DVB_VES1X93=m +CONFIG_DVB_TUNER_ITD1000=m +CONFIG_DVB_TUNER_CX24113=m +CONFIG_DVB_TDA826X=m +CONFIG_DVB_TUA6100=m +CONFIG_DVB_CX24116=m +CONFIG_DVB_SI21XX=m + +# +# DVB-T (terrestrial) frontends +# +CONFIG_DVB_SP8870=m +CONFIG_DVB_SP887X=m +CONFIG_DVB_CX22700=m +CONFIG_DVB_CX22702=m +# CONFIG_DVB_DRX397XD is not set +CONFIG_DVB_L64781=m +CONFIG_DVB_TDA1004X=m +CONFIG_DVB_NXT6000=m +CONFIG_DVB_MT352=m +CONFIG_DVB_ZL10353=m +CONFIG_DVB_DIB3000MB=m +CONFIG_DVB_DIB3000MC=m +CONFIG_DVB_DIB7000M=m +CONFIG_DVB_DIB7000P=m +CONFIG_DVB_TDA10048=m +CONFIG_DVB_AF9013=m + +# +# DVB-C (cable) frontends +# +CONFIG_DVB_VES1820=m +CONFIG_DVB_TDA10021=m +CONFIG_DVB_TDA10023=m +CONFIG_DVB_STV0297=m + +# +# ATSC (North American/Korean Terrestrial/Cable DTV) frontends +# +CONFIG_DVB_NXT200X=m +CONFIG_DVB_OR51211=m +CONFIG_DVB_OR51132=m +CONFIG_DVB_BCM3510=m +CONFIG_DVB_LGDT330X=m +# CONFIG_DVB_LGDT3304 is not set +CONFIG_DVB_LGDT3305=m +CONFIG_DVB_S5H1409=m +CONFIG_DVB_AU8522=m +CONFIG_DVB_S5H1411=m + +# +# ISDB-T (terrestrial) frontends +# +# CONFIG_DVB_S921 is not set +CONFIG_DVB_DIB8000=m + +# +# Digital terrestrial only tuners/PLL +# +CONFIG_DVB_PLL=m +CONFIG_DVB_TUNER_DIB0070=m + +# +# SEC control devices for DVB-S +# +CONFIG_DVB_LNBP21=m +CONFIG_DVB_ISL6405=m +CONFIG_DVB_ISL6421=m +# CONFIG_DVB_ISL6423 is not set +CONFIG_DVB_LGS8GL5=m +CONFIG_DVB_LGS8GXX=m + +# +# Tools to develop new frontends +# +# CONFIG_DVB_DUMMY_FE is not set +CONFIG_DAB=y +CONFIG_USB_DABUSB=m + +# +# Graphics support +# +CONFIG_AGP=m +CONFIG_AGP_ALI=m +CONFIG_AGP_ATI=m +CONFIG_AGP_AMD=m +CONFIG_AGP_AMD64=m +CONFIG_AGP_INTEL=m +CONFIG_AGP_NVIDIA=m +CONFIG_AGP_SIS=m +CONFIG_AGP_SWORKS=m +CONFIG_AGP_VIA=m +CONFIG_AGP_EFFICEON=m +CONFIG_VGA_ARB=y +CONFIG_DRM=m +CONFIG_DRM_KMS_HELPER=m +CONFIG_DRM_TTM=m +CONFIG_DRM_TDFX=m +CONFIG_DRM_R128=m +CONFIG_DRM_RADEON=m +CONFIG_DRM_I810=m +CONFIG_DRM_I830=m +CONFIG_DRM_I915=m +CONFIG_DRM_I915_KMS=y +CONFIG_DRM_MGA=m +CONFIG_DRM_SIS=m +CONFIG_DRM_VIA=m +CONFIG_DRM_SAVAGE=m +CONFIG_VGASTATE=m +CONFIG_VIDEO_OUTPUT_CONTROL=m +CONFIG_FB=y +CONFIG_FIRMWARE_EDID=y +CONFIG_FB_DDC=m +CONFIG_FB_BOOT_VESA_SUPPORT=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +CONFIG_FB_SYS_FILLRECT=m +CONFIG_FB_SYS_COPYAREA=m +CONFIG_FB_SYS_IMAGEBLIT=m +# CONFIG_FB_FOREIGN_ENDIAN is not set +CONFIG_FB_SYS_FOPS=m +CONFIG_FB_DEFERRED_IO=y +CONFIG_FB_HECUBA=m +CONFIG_FB_SVGALIB=m +# CONFIG_FB_MACMODES is not set +CONFIG_FB_BACKLIGHT=y +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_TILEBLITTING=y + +# +# Frame buffer hardware drivers +# +CONFIG_FB_CIRRUS=m +CONFIG_FB_PM2=m +CONFIG_FB_PM2_FIFO_DISCONNECT=y +CONFIG_FB_CYBER2000=m +CONFIG_FB_ARC=m +# CONFIG_FB_ASILIANT is not set +# CONFIG_FB_IMSTT is not set +CONFIG_FB_VGA16=m +CONFIG_FB_UVESA=m +CONFIG_FB_VESA=y +CONFIG_FB_N411=m +CONFIG_FB_HGA=m +CONFIG_FB_HGA_ACCEL=y +CONFIG_FB_S1D13XXX=m +CONFIG_FB_NVIDIA=m +CONFIG_FB_NVIDIA_I2C=y +# CONFIG_FB_NVIDIA_DEBUG is not set +CONFIG_FB_NVIDIA_BACKLIGHT=y +CONFIG_FB_RIVA=m +CONFIG_FB_RIVA_I2C=y +# CONFIG_FB_RIVA_DEBUG is not set +CONFIG_FB_RIVA_BACKLIGHT=y +CONFIG_FB_I810=m +CONFIG_FB_I810_GTF=y +CONFIG_FB_I810_I2C=y +CONFIG_FB_LE80578=m +CONFIG_FB_CARILLO_RANCH=m +CONFIG_FB_MATROX=m +CONFIG_FB_MATROX_MILLENIUM=y +CONFIG_FB_MATROX_MYSTIQUE=y +CONFIG_FB_MATROX_G=y +CONFIG_FB_MATROX_I2C=m +CONFIG_FB_MATROX_MAVEN=m +CONFIG_FB_RADEON=m +CONFIG_FB_RADEON_I2C=y +CONFIG_FB_RADEON_BACKLIGHT=y +# CONFIG_FB_RADEON_DEBUG is not set +CONFIG_FB_ATY128=m +CONFIG_FB_ATY128_BACKLIGHT=y +CONFIG_FB_ATY=m +CONFIG_FB_ATY_CT=y +CONFIG_FB_ATY_GENERIC_LCD=y +CONFIG_FB_ATY_GX=y +CONFIG_FB_ATY_BACKLIGHT=y +CONFIG_FB_S3=m +CONFIG_FB_SAVAGE=m +CONFIG_FB_SAVAGE_I2C=y +CONFIG_FB_SAVAGE_ACCEL=y +CONFIG_FB_SIS=m +CONFIG_FB_SIS_300=y +CONFIG_FB_SIS_315=y +CONFIG_FB_VIA=m +CONFIG_FB_NEOMAGIC=m +CONFIG_FB_KYRO=m +CONFIG_FB_3DFX=m +CONFIG_FB_3DFX_ACCEL=y +CONFIG_FB_3DFX_I2C=y +CONFIG_FB_VOODOO1=m +CONFIG_FB_VT8623=m +CONFIG_FB_TRIDENT=m +CONFIG_FB_ARK=m +CONFIG_FB_PM3=m +CONFIG_FB_CARMINE=m +CONFIG_FB_CARMINE_DRAM_EVAL=y +# CONFIG_CARMINE_DRAM_CUSTOM is not set +CONFIG_FB_GEODE=y +CONFIG_FB_GEODE_LX=m +CONFIG_FB_GEODE_GX=m +CONFIG_FB_GEODE_GX1=m +CONFIG_FB_TMIO=m +CONFIG_FB_TMIO_ACCELL=y +CONFIG_FB_SM501=m +CONFIG_FB_VIRTUAL=m +CONFIG_FB_METRONOME=m +CONFIG_FB_MB862XX=m +CONFIG_FB_MB862XX_PCI_GDC=y +CONFIG_FB_BROADSHEET=m +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_LCD_CLASS_DEVICE=m +CONFIG_LCD_LMS283GF05=m +CONFIG_LCD_LTV350QV=m +CONFIG_LCD_ILI9320=m +CONFIG_LCD_TDO24M=m +CONFIG_LCD_VGG2432A4=m +CONFIG_LCD_PLATFORM=m +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_BACKLIGHT_GENERIC=m +CONFIG_BACKLIGHT_PROGEAR=m +CONFIG_BACKLIGHT_CARILLO_RANCH=m +CONFIG_BACKLIGHT_MBP_NVIDIA=m +CONFIG_BACKLIGHT_SAHARA=m + +# +# Display device support +# +CONFIG_DISPLAY_SUPPORT=m + +# +# Display hardware drivers +# + +# +# Console display driver support +# +CONFIG_VGA_CONSOLE=y +CONFIG_VGACON_SOFT_SCROLLBACK=y +CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64 +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +# CONFIG_LOGO is not set +CONFIG_SOUND=m +CONFIG_SOUND_OSS_CORE=y +# CONFIG_SOUND_OSS_CORE_PRECLAIM is not set +CONFIG_SND=m +CONFIG_SND_TIMER=m +CONFIG_SND_PCM=m +CONFIG_SND_HWDEP=m +CONFIG_SND_RAWMIDI=m +CONFIG_SND_JACK=y +CONFIG_SND_SEQUENCER=m +CONFIG_SND_SEQ_DUMMY=m +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=m +CONFIG_SND_PCM_OSS=m +CONFIG_SND_PCM_OSS_PLUGINS=y +CONFIG_SND_SEQUENCER_OSS=y +CONFIG_SND_DYNAMIC_MINORS=y +CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_VERBOSE_PROCFS=y +CONFIG_SND_VERBOSE_PRINTK=y +CONFIG_SND_DEBUG=y +# CONFIG_SND_DEBUG_VERBOSE is not set +CONFIG_SND_PCM_XRUN_DEBUG=y +CONFIG_SND_VMASTER=y +CONFIG_SND_DMA_SGBUF=y +CONFIG_SND_RAWMIDI_SEQ=m +CONFIG_SND_OPL3_LIB_SEQ=m +# CONFIG_SND_OPL4_LIB_SEQ is not set +# CONFIG_SND_SBAWE_SEQ is not set +CONFIG_SND_EMU10K1_SEQ=m +CONFIG_SND_MPU401_UART=m +CONFIG_SND_OPL3_LIB=m +CONFIG_SND_VX_LIB=m +CONFIG_SND_AC97_CODEC=m +CONFIG_SND_DRIVERS=y +CONFIG_SND_DUMMY=m +CONFIG_SND_VIRMIDI=m +CONFIG_SND_MTPAV=m +CONFIG_SND_MTS64=m +CONFIG_SND_SERIAL_U16550=m +CONFIG_SND_MPU401=m +CONFIG_SND_PORTMAN2X4=m +CONFIG_SND_AC97_POWER_SAVE=y +CONFIG_SND_AC97_POWER_SAVE_DEFAULT=0 +CONFIG_SND_SB_COMMON=m +CONFIG_SND_SB16_DSP=m +CONFIG_SND_PCI=y +CONFIG_SND_AD1889=m +CONFIG_SND_ALS300=m +CONFIG_SND_ALS4000=m +CONFIG_SND_ALI5451=m +CONFIG_SND_ATIIXP=m +CONFIG_SND_ATIIXP_MODEM=m +CONFIG_SND_AU8810=m +CONFIG_SND_AU8820=m +CONFIG_SND_AU8830=m +CONFIG_SND_AW2=m +CONFIG_SND_AZT3328=m +CONFIG_SND_BT87X=m +# CONFIG_SND_BT87X_OVERCLOCK is not set +CONFIG_SND_CA0106=m +CONFIG_SND_CMIPCI=m +CONFIG_SND_OXYGEN_LIB=m +CONFIG_SND_OXYGEN=m +CONFIG_SND_CS4281=m +CONFIG_SND_CS46XX=m +CONFIG_SND_CS46XX_NEW_DSP=y +CONFIG_SND_CS5530=m +CONFIG_SND_CS5535AUDIO=m +CONFIG_SND_CTXFI=m +CONFIG_SND_DARLA20=m +CONFIG_SND_GINA20=m +CONFIG_SND_LAYLA20=m +CONFIG_SND_DARLA24=m +CONFIG_SND_GINA24=m +CONFIG_SND_LAYLA24=m +CONFIG_SND_MONA=m +CONFIG_SND_MIA=m +CONFIG_SND_ECHO3G=m +CONFIG_SND_INDIGO=m +CONFIG_SND_INDIGOIO=m +CONFIG_SND_INDIGODJ=m +CONFIG_SND_INDIGOIOX=m +CONFIG_SND_INDIGODJX=m +CONFIG_SND_EMU10K1=m +CONFIG_SND_EMU10K1X=m +CONFIG_SND_ENS1370=m +CONFIG_SND_ENS1371=m +CONFIG_SND_ES1938=m +CONFIG_SND_ES1968=m +CONFIG_SND_FM801=m +CONFIG_SND_FM801_TEA575X_BOOL=y +CONFIG_SND_FM801_TEA575X=m +CONFIG_SND_HDA_INTEL=m +CONFIG_SND_HDA_HWDEP=y +CONFIG_SND_HDA_RECONFIG=y +CONFIG_SND_HDA_INPUT_BEEP=y +CONFIG_SND_HDA_INPUT_JACK=y +CONFIG_SND_HDA_PATCH_LOADER=y +CONFIG_SND_HDA_CODEC_REALTEK=y +CONFIG_SND_HDA_CODEC_ANALOG=y +CONFIG_SND_HDA_CODEC_SIGMATEL=y +CONFIG_SND_HDA_CODEC_VIA=y +CONFIG_SND_HDA_CODEC_ATIHDMI=y +CONFIG_SND_HDA_CODEC_NVHDMI=y +CONFIG_SND_HDA_CODEC_INTELHDMI=y +CONFIG_SND_HDA_ELD=y +CONFIG_SND_HDA_CODEC_CIRRUS=y +CONFIG_SND_HDA_CODEC_CONEXANT=y +CONFIG_SND_HDA_CODEC_CA0110=y +CONFIG_SND_HDA_CODEC_CMEDIA=y +CONFIG_SND_HDA_CODEC_SI3054=y +CONFIG_SND_HDA_GENERIC=y +CONFIG_SND_HDA_POWER_SAVE=y +CONFIG_SND_HDA_POWER_SAVE_DEFAULT=0 +CONFIG_SND_HDSP=m +CONFIG_SND_HDSPM=m +CONFIG_SND_HIFIER=m +CONFIG_SND_ICE1712=m +CONFIG_SND_ICE1724=m +CONFIG_SND_INTEL8X0=m +CONFIG_SND_INTEL8X0M=m +CONFIG_SND_KORG1212=m +CONFIG_SND_LX6464ES=m +CONFIG_SND_MAESTRO3=m +CONFIG_SND_MIXART=m +CONFIG_SND_NM256=m +CONFIG_SND_PCXHR=m +CONFIG_SND_RIPTIDE=m +CONFIG_SND_RME32=m +CONFIG_SND_RME96=m +CONFIG_SND_RME9652=m +CONFIG_SND_SIS7019=m +CONFIG_SND_SONICVIBES=m +CONFIG_SND_TRIDENT=m +CONFIG_SND_VIA82XX=m +CONFIG_SND_VIA82XX_MODEM=m +CONFIG_SND_VIRTUOSO=m +CONFIG_SND_VX222=m +CONFIG_SND_YMFPCI=m +CONFIG_SND_SPI=y +CONFIG_SND_USB=y +CONFIG_SND_USB_AUDIO=m +CONFIG_SND_USB_USX2Y=m +CONFIG_SND_USB_CAIAQ=m +CONFIG_SND_USB_CAIAQ_INPUT=y +CONFIG_SND_USB_US122L=m +CONFIG_SND_PCMCIA=y +CONFIG_SND_VXPOCKET=m +CONFIG_SND_PDAUDIOCF=m +# CONFIG_SND_SOC is not set +CONFIG_SOUND_PRIME=m +CONFIG_SOUND_OSS=m +CONFIG_SOUND_TRACEINIT=y +CONFIG_SOUND_DMAP=y +CONFIG_SOUND_SSCAPE=m +CONFIG_SOUND_VMIDI=m +CONFIG_SOUND_TRIX=m +CONFIG_SOUND_MSS=m +CONFIG_SOUND_MPU401=m +CONFIG_SOUND_PAS=m +CONFIG_SOUND_PSS=m +CONFIG_PSS_MIXER=y +# CONFIG_PSS_HAVE_BOOT is not set +# CONFIG_SOUND_SB is not set +CONFIG_SOUND_YM3812=m +CONFIG_SOUND_UART6850=m +CONFIG_SOUND_AEDSP16=m +CONFIG_SC6600=y +CONFIG_SC6600_JOY=y +CONFIG_SC6600_CDROM=4 +CONFIG_SC6600_CDROMBASE=0 +CONFIG_AC97_BUS=m +CONFIG_HID_SUPPORT=y +CONFIG_HID=m +CONFIG_HIDRAW=y + +# +# USB Input Devices +# +CONFIG_USB_HID=m +CONFIG_HID_PID=y +CONFIG_USB_HIDDEV=y + +# +# Special HID drivers +# +CONFIG_HID_A4TECH=m +CONFIG_HID_APPLE=m +CONFIG_HID_BELKIN=m +CONFIG_HID_CHERRY=m +CONFIG_HID_CHICONY=m +CONFIG_HID_CYPRESS=m +CONFIG_HID_DRAGONRISE=m +CONFIG_DRAGONRISE_FF=y +CONFIG_HID_EZKEY=m +CONFIG_HID_KYE=m +CONFIG_HID_GYRATION=m +CONFIG_HID_TWINHAN=m +CONFIG_HID_KENSINGTON=m +CONFIG_HID_LOGITECH=m +CONFIG_LOGITECH_FF=y +CONFIG_LOGIRUMBLEPAD2_FF=y +CONFIG_HID_MICROSOFT=m +CONFIG_HID_MONTEREY=m +CONFIG_HID_NTRIG=m +CONFIG_HID_PANTHERLORD=m +CONFIG_PANTHERLORD_FF=y +CONFIG_HID_PETALYNX=m +CONFIG_HID_SAMSUNG=m +CONFIG_HID_SONY=m +CONFIG_HID_SUNPLUS=m +CONFIG_HID_GREENASIA=m +CONFIG_GREENASIA_FF=y +CONFIG_HID_SMARTJOYPLUS=m +CONFIG_SMARTJOYPLUS_FF=y +CONFIG_HID_TOPSEED=m +CONFIG_HID_THRUSTMASTER=m +CONFIG_THRUSTMASTER_FF=y +CONFIG_HID_WACOM=m +CONFIG_HID_ZEROPLUS=m +CONFIG_ZEROPLUS_FF=y +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB=m +# CONFIG_USB_DEBUG is not set +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_DEVICE_CLASS is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +CONFIG_USB_SUSPEND=y +# CONFIG_USB_OTG is not set +CONFIG_USB_MON=m +CONFIG_USB_WUSB=m +CONFIG_USB_WUSB_CBAF=m +# CONFIG_USB_WUSB_CBAF_DEBUG is not set + +# +# USB Host Controller Drivers +# +CONFIG_USB_C67X00_HCD=m +CONFIG_USB_XHCI_HCD=m +# CONFIG_USB_XHCI_HCD_DEBUGGING is not set +CONFIG_USB_EHCI_HCD=m +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +CONFIG_USB_OXU210HP_HCD=m +CONFIG_USB_ISP116X_HCD=m +CONFIG_USB_ISP1760_HCD=m +CONFIG_USB_ISP1362_HCD=m +CONFIG_USB_OHCI_HCD=m +# CONFIG_USB_OHCI_HCD_SSB is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +CONFIG_USB_UHCI_HCD=m +CONFIG_USB_U132_HCD=m +CONFIG_USB_SL811_HCD=m +CONFIG_USB_SL811_CS=m +CONFIG_USB_R8A66597_HCD=m +CONFIG_USB_WHCI_HCD=m +CONFIG_USB_HWA_HCD=m + +# +# Enable Host or Gadget support to see Inventra options +# + +# +# USB Device Class drivers +# +CONFIG_USB_ACM=m +CONFIG_USB_PRINTER=m +CONFIG_USB_WDM=m +CONFIG_USB_TMC=m + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may +# + +# +# also be needed; see USB_STORAGE Help for more info +# +CONFIG_USB_STORAGE=m +# CONFIG_USB_STORAGE_DEBUG is not set +CONFIG_USB_STORAGE_DATAFAB=m +CONFIG_USB_STORAGE_FREECOM=m +CONFIG_USB_STORAGE_ISD200=m +CONFIG_USB_STORAGE_USBAT=m +CONFIG_USB_STORAGE_SDDR09=m +CONFIG_USB_STORAGE_SDDR55=m +CONFIG_USB_STORAGE_JUMPSHOT=m +CONFIG_USB_STORAGE_ALAUDA=m +CONFIG_USB_STORAGE_ONETOUCH=m +CONFIG_USB_STORAGE_KARMA=m +CONFIG_USB_STORAGE_CYPRESS_ATACB=m +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Imaging devices +# +CONFIG_USB_MDC800=m +CONFIG_USB_MICROTEK=m + +# +# USB port drivers +# +CONFIG_USB_USS720=m +CONFIG_USB_SERIAL=m +CONFIG_USB_EZUSB=y +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_AIRCABLE=m +CONFIG_USB_SERIAL_ARK3116=m +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_CH341=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_CP210X=m +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_FUNSOFT=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_GARMIN=m +CONFIG_USB_SERIAL_IPW=m +CONFIG_USB_SERIAL_IUU=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +CONFIG_USB_SERIAL_KEYSPAN_MPR=y +CONFIG_USB_SERIAL_KEYSPAN_USA28=y +CONFIG_USB_SERIAL_KEYSPAN_USA28X=y +CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y +CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y +CONFIG_USB_SERIAL_KEYSPAN_USA19=y +CONFIG_USB_SERIAL_KEYSPAN_USA18X=y +CONFIG_USB_SERIAL_KEYSPAN_USA19W=y +CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y +CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y +CONFIG_USB_SERIAL_KEYSPAN_USA49W=y +CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_MOS7720=m +CONFIG_USB_SERIAL_MOS7840=m +CONFIG_USB_SERIAL_MOTOROLA=m +CONFIG_USB_SERIAL_NAVMAN=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_OTI6858=m +CONFIG_USB_SERIAL_QUALCOMM=m +CONFIG_USB_SERIAL_SPCP8X5=m +CONFIG_USB_SERIAL_HP4X=m +CONFIG_USB_SERIAL_SAFE=m +CONFIG_USB_SERIAL_SAFE_PADDED=y +CONFIG_USB_SERIAL_SIEMENS_MPI=m +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +CONFIG_USB_SERIAL_SYMBOL=m +CONFIG_USB_SERIAL_TI=m +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_XIRCOM=m +CONFIG_USB_SERIAL_OPTION=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_SERIAL_OPTICON=m +CONFIG_USB_SERIAL_DEBUG=m + +# +# USB Miscellaneous drivers +# +CONFIG_USB_EMI62=m +CONFIG_USB_EMI26=m +CONFIG_USB_ADUTUX=m +CONFIG_USB_SEVSEG=m +CONFIG_USB_RIO500=m +CONFIG_USB_LEGOTOWER=m +CONFIG_USB_LCD=m +CONFIG_USB_BERRY_CHARGE=m +CONFIG_USB_LED=m +CONFIG_USB_CYPRESS_CY7C63=m +CONFIG_USB_CYTHERM=m +CONFIG_USB_IDMOUSE=m +CONFIG_USB_FTDI_ELAN=m +CONFIG_USB_APPLEDISPLAY=m +CONFIG_USB_SISUSBVGA=m +CONFIG_USB_SISUSBVGA_CON=y +CONFIG_USB_LD=m +CONFIG_USB_TRANCEVIBRATOR=m +CONFIG_USB_IOWARRIOR=m +# CONFIG_USB_TEST is not set +CONFIG_USB_ISIGHTFW=m +CONFIG_USB_VST=m +CONFIG_USB_ATM=m +CONFIG_USB_SPEEDTOUCH=m +CONFIG_USB_CXACRU=m +CONFIG_USB_UEAGLEATM=m +CONFIG_USB_XUSBATM=m +# CONFIG_USB_GADGET is not set + +# +# OTG and related infrastructure +# +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_NOP_USB_XCEIV is not set +CONFIG_UWB=m +CONFIG_UWB_HWA=m +CONFIG_UWB_WHCI=m +CONFIG_UWB_WLP=m +CONFIG_UWB_I1480U=m +CONFIG_UWB_I1480U_WLP=m +CONFIG_MMC=m +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_UNSAFE_RESUME is not set + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=m +CONFIG_MMC_BLOCK_BOUNCE=y +CONFIG_SDIO_UART=m +CONFIG_MMC_TEST=m + +# +# MMC/SD/SDIO Host Controller Drivers +# +CONFIG_MMC_SDHCI=m +CONFIG_MMC_SDHCI_PCI=m +CONFIG_MMC_RICOH_MMC=m +CONFIG_MMC_SDHCI_PLTFM=m +CONFIG_MMC_WBSD=m +# CONFIG_MMC_AT91 is not set +# CONFIG_MMC_ATMELMCI is not set +CONFIG_MMC_TIFM_SD=m +CONFIG_MMC_SDRICOH_CS=m +CONFIG_MMC_CB710=m +CONFIG_MMC_VIA_SDMMC=m +CONFIG_MEMSTICK=m +# CONFIG_MEMSTICK_DEBUG is not set + +# +# MemoryStick drivers +# +# CONFIG_MEMSTICK_UNSAFE_RESUME is not set +CONFIG_MSPRO_BLOCK=m + +# +# MemoryStick Host Controller Drivers +# +CONFIG_MEMSTICK_TIFM_MS=m +CONFIG_MEMSTICK_JMICRON_38X=m +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=m + +# +# LED drivers +# +CONFIG_LEDS_NET48XX=m +CONFIG_LEDS_WRAP=m +CONFIG_LEDS_ALIX2=m +CONFIG_LEDS_PCA9532=m +CONFIG_LEDS_GPIO=m +CONFIG_LEDS_GPIO_PLATFORM=y +CONFIG_LEDS_LP3944=m +CONFIG_LEDS_CLEVO_MAIL=m +CONFIG_LEDS_PCA955X=m +CONFIG_LEDS_DAC124S085=m +CONFIG_LEDS_BD2802=m + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=m +CONFIG_LEDS_TRIGGER_IDE_DISK=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=m +CONFIG_LEDS_TRIGGER_BACKLIGHT=m +CONFIG_LEDS_TRIGGER_GPIO=m +CONFIG_LEDS_TRIGGER_DEFAULT_ON=m + +# +# iptables trigger is under Netfilter config (LED target) +# +# CONFIG_ACCESSIBILITY is not set +CONFIG_INFINIBAND=m +CONFIG_INFINIBAND_USER_MAD=m +CONFIG_INFINIBAND_USER_ACCESS=m +CONFIG_INFINIBAND_USER_MEM=y +CONFIG_INFINIBAND_ADDR_TRANS=y +CONFIG_INFINIBAND_MTHCA=m +CONFIG_INFINIBAND_MTHCA_DEBUG=y +CONFIG_INFINIBAND_AMSO1100=m +# CONFIG_INFINIBAND_AMSO1100_DEBUG is not set +CONFIG_INFINIBAND_CXGB3=m +# CONFIG_INFINIBAND_CXGB3_DEBUG is not set +CONFIG_MLX4_INFINIBAND=m +CONFIG_INFINIBAND_NES=m +# CONFIG_INFINIBAND_NES_DEBUG is not set +CONFIG_INFINIBAND_IPOIB=m +CONFIG_INFINIBAND_IPOIB_CM=y +CONFIG_INFINIBAND_IPOIB_DEBUG=y +# CONFIG_INFINIBAND_IPOIB_DEBUG_DATA is not set +CONFIG_INFINIBAND_SRP=m +CONFIG_INFINIBAND_ISER=m +CONFIG_EDAC=y + +# +# Reporting subsystems +# +# CONFIG_EDAC_DEBUG is not set +CONFIG_EDAC_DECODE_MCE=m +CONFIG_EDAC_MM_EDAC=m +CONFIG_EDAC_AMD76X=m +CONFIG_EDAC_E7XXX=m +CONFIG_EDAC_E752X=m +CONFIG_EDAC_I82875P=m +CONFIG_EDAC_I82975X=m +CONFIG_EDAC_I3000=m +CONFIG_EDAC_I3200=m +CONFIG_EDAC_X38=m +CONFIG_EDAC_I5400=m +CONFIG_EDAC_I82860=m +CONFIG_EDAC_R82600=m +CONFIG_EDAC_I5000=m +CONFIG_EDAC_I5100=m +CONFIG_RTC_LIB=m +CONFIG_RTC_CLASS=m + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +CONFIG_RTC_INTF_DEV_UIE_EMUL=y +CONFIG_RTC_DRV_TEST=m + +# +# I2C RTC drivers +# +CONFIG_RTC_DRV_DS1307=m +CONFIG_RTC_DRV_DS1374=m +CONFIG_RTC_DRV_DS1672=m +CONFIG_RTC_DRV_MAX6900=m +CONFIG_RTC_DRV_RS5C372=m +CONFIG_RTC_DRV_ISL1208=m +CONFIG_RTC_DRV_X1205=m +CONFIG_RTC_DRV_PCF8563=m +CONFIG_RTC_DRV_PCF8583=m +CONFIG_RTC_DRV_M41T80=m +CONFIG_RTC_DRV_M41T80_WDT=y +CONFIG_RTC_DRV_S35390A=m +CONFIG_RTC_DRV_FM3130=m +CONFIG_RTC_DRV_RX8581=m +CONFIG_RTC_DRV_RX8025=m + +# +# SPI RTC drivers +# +CONFIG_RTC_DRV_M41T94=m +CONFIG_RTC_DRV_DS1305=m +CONFIG_RTC_DRV_DS1390=m +CONFIG_RTC_DRV_MAX6902=m +CONFIG_RTC_DRV_R9701=m +CONFIG_RTC_DRV_RS5C348=m +CONFIG_RTC_DRV_DS3234=m +CONFIG_RTC_DRV_PCF2123=m + +# +# Platform RTC drivers +# +CONFIG_RTC_DRV_CMOS=m +CONFIG_RTC_DRV_DS1286=m +CONFIG_RTC_DRV_DS1511=m +CONFIG_RTC_DRV_DS1553=m +CONFIG_RTC_DRV_DS1742=m +CONFIG_RTC_DRV_STK17TA8=m +CONFIG_RTC_DRV_M48T86=m +CONFIG_RTC_DRV_M48T35=m +CONFIG_RTC_DRV_M48T59=m +CONFIG_RTC_DRV_BQ4802=m +CONFIG_RTC_DRV_V3020=m +CONFIG_RTC_DRV_AB3100=m + +# +# on-CPU RTC drivers +# +CONFIG_RTC_DRV_PCAP=m +CONFIG_DMADEVICES=y + +# +# DMA Devices +# +CONFIG_ASYNC_TX_DISABLE_CHANNEL_SWITCH=y +CONFIG_INTEL_IOATDMA=m +CONFIG_DMA_ENGINE=y + +# +# DMA Clients +# +CONFIG_NET_DMA=y +CONFIG_ASYNC_TX_DMA=y +CONFIG_DMATEST=m +CONFIG_DCA=m +CONFIG_AUXDISPLAY=y +CONFIG_KS0108=m +CONFIG_KS0108_PORT=0x378 +CONFIG_KS0108_DELAY=2 +CONFIG_CFAG12864B=m +CONFIG_CFAG12864B_RATE=20 +CONFIG_UIO=m +CONFIG_UIO_CIF=m +CONFIG_UIO_PDRV=m +CONFIG_UIO_PDRV_GENIRQ=m +CONFIG_UIO_SMX=m +CONFIG_UIO_AEC=m +CONFIG_UIO_SERCOS3=m +CONFIG_UIO_PCI_GENERIC=m + +# +# TI VLYNQ +# +CONFIG_XEN=y +CONFIG_XEN_INTERFACE_VERSION=0x00030207 + +# +# XEN +# +CONFIG_XEN_PRIVILEGED_GUEST=y +# CONFIG_XEN_UNPRIVILEGED_GUEST is not set +CONFIG_XEN_PRIVCMD=y +CONFIG_XEN_DOMCTL=m +CONFIG_XEN_XENBUS_DEV=y +CONFIG_XEN_NETDEV_ACCEL_SFC_UTIL=m +CONFIG_XEN_BACKEND=m +CONFIG_XEN_BLKDEV_BACKEND=m +CONFIG_XEN_BLKDEV_TAP=m +CONFIG_XEN_BLKDEV_TAP2=m +CONFIG_XEN_BLKBACK_PAGEMAP=m +CONFIG_XEN_NETDEV_BACKEND=m +CONFIG_XEN_NETDEV_TX_SHIFT=10 +# CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set +CONFIG_XEN_NETDEV_ACCEL_SFC_BACKEND=m +CONFIG_XEN_NETDEV_LOOPBACK=m +CONFIG_XEN_PCIDEV_BACKEND=m +CONFIG_XEN_PCIDEV_BACKEND_VPCI=y +# CONFIG_XEN_PCIDEV_BACKEND_PASS is not set +# CONFIG_XEN_PCIDEV_BACKEND_SLOT is not set +# CONFIG_XEN_PCIDEV_BACKEND_CONTROLLER is not set +# CONFIG_XEN_PCIDEV_BE_DEBUG is not set +CONFIG_XEN_TPMDEV_BACKEND=m +CONFIG_XEN_SCSI_BACKEND=m +CONFIG_XEN_USB_BACKEND=m +CONFIG_XEN_BLKDEV_FRONTEND=m +CONFIG_XEN_NETDEV_FRONTEND=m +CONFIG_XEN_NETDEV_ACCEL_SFC_FRONTEND=m +CONFIG_XEN_SCSI_FRONTEND=m +CONFIG_XEN_USB_FRONTEND=m +# CONFIG_XEN_USB_FRONTEND_HCD_STATS is not set +# CONFIG_XEN_USB_FRONTEND_HCD_PM is not set +CONFIG_XEN_GRANT_DEV=m +CONFIG_XEN_FRAMEBUFFER=y +CONFIG_XEN_KEYBOARD=y +# CONFIG_XEN_DISABLE_SERIAL is not set +CONFIG_XEN_SYSFS=y +CONFIG_XEN_NR_GUEST_DEVICES=256 +# CONFIG_XEN_COMPAT_030002_AND_LATER is not set +# CONFIG_XEN_COMPAT_030004_AND_LATER is not set +# CONFIG_XEN_COMPAT_030100_AND_LATER is not set +CONFIG_XEN_COMPAT_030200_AND_LATER=y +# CONFIG_XEN_COMPAT_030300_AND_LATER is not set +# CONFIG_XEN_COMPAT_030400_AND_LATER is not set +# CONFIG_XEN_COMPAT_LATEST_ONLY is not set +CONFIG_XEN_COMPAT=0x030200 +CONFIG_XEN_VCPU_INFO_PLACEMENT=y +CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y +CONFIG_IRQ_PER_CPU=y +CONFIG_NO_IDLE_HZ=y +CONFIG_XEN_SMPBOOT=y +CONFIG_XEN_DEVMEM=y +CONFIG_XEN_BALLOON=y +CONFIG_XEN_SCRUB_PAGES=y +CONFIG_STAGING=y +# CONFIG_STAGING_EXCLUDE_BUILD is not set +CONFIG_ET131X=m +# CONFIG_ET131X_DEBUG is not set +CONFIG_SLICOSS=m +CONFIG_VIDEO_GO7007=m +CONFIG_VIDEO_GO7007_USB=m +CONFIG_VIDEO_GO7007_USB_S2250_BOARD=m +CONFIG_VIDEO_GO7007_OV7640=m +CONFIG_VIDEO_GO7007_SAA7113=m +CONFIG_VIDEO_GO7007_SAA7115=m +CONFIG_VIDEO_GO7007_TW9903=m +CONFIG_VIDEO_GO7007_UDA1342=m +CONFIG_VIDEO_GO7007_SONY_TUNER=m +CONFIG_VIDEO_GO7007_TW2804=m +CONFIG_VIDEO_CX25821=m +CONFIG_VIDEO_CX25821_ALSA=m +CONFIG_USB_IP_COMMON=m +CONFIG_USB_IP_VHCI_HCD=m +CONFIG_USB_IP_HOST=m +CONFIG_W35UND=m +CONFIG_PRISM2_USB=m +CONFIG_ECHO=m +CONFIG_POCH=m +CONFIG_OTUS=m +CONFIG_RT2860=m +CONFIG_RT2870=m +CONFIG_RT3090=m +# CONFIG_COMEDI is not set +CONFIG_ASUS_OLED=m +CONFIG_PANEL=m +CONFIG_PANEL_PARPORT=0 +CONFIG_PANEL_PROFILE=5 +# CONFIG_PANEL_CHANGE_MESSAGE is not set +CONFIG_ALTERA_PCIE_CHDMA=m +CONFIG_RTL8187SE=m +CONFIG_RTL8192SU=m +CONFIG_RTL8192E=m +CONFIG_TRANZPORT=m + +# +# Android +# + +# +# Qualcomm MSM Camera And Video +# + +# +# Camera Sensor Selection +# +CONFIG_INPUT_GPIO=m +CONFIG_DST=m +# CONFIG_DST_DEBUG is not set +CONFIG_POHMELFS=m +# CONFIG_POHMELFS_DEBUG is not set +CONFIG_POHMELFS_CRYPTO=y +CONFIG_B3DFG=m +CONFIG_IDE_PHISON=m +CONFIG_PLAN9AUTH=m +CONFIG_LINE6_USB=m +# CONFIG_DRM_RADEON_KMS is not set +CONFIG_USB_SERIAL_QUATECH2=m +CONFIG_USB_SERIAL_QUATECH_USB2=m +CONFIG_VT6655=m +CONFIG_VT6656=m +CONFIG_FB_UDL=m +CONFIG_VME_BUS=m + +# +# VME Bridge Drivers +# +CONFIG_VME_CA91CX42=m +CONFIG_VME_TSI148=m + +# +# VME Device Drivers +# +CONFIG_VME_USER=m + +# +# RAR Register Driver +# +CONFIG_RAR_REGISTER=m +CONFIG_DX_SEP=m +CONFIG_IIO=m +CONFIG_IIO_RING_BUFFER=y +CONFIG_IIO_SW_RING=m +CONFIG_IIO_TRIGGER=y + +# +# Accelerometers +# +CONFIG_KXSD9=m +CONFIG_LIS3L02DQ=m +CONFIG_SCA3000=m + +# +# Analog to digital convertors +# +CONFIG_MAX1363=m + +# +# Light sensors +# +CONFIG_TSL2561=m + +# +# Triggers - standalone +# +CONFIG_IIO_PERIODIC_RTC_TRIGGER=m +CONFIG_IIO_GPIO_TRIGGER=m +CONFIG_X86_PLATFORM_DEVICES=y +CONFIG_ACER_WMI=m +CONFIG_ACERHDF=m +CONFIG_ASUS_LAPTOP=m +CONFIG_DELL_WMI=m +CONFIG_FUJITSU_LAPTOP=m +# CONFIG_FUJITSU_LAPTOP_DEBUG is not set +CONFIG_TC1100_WMI=m +CONFIG_HP_WMI=m +CONFIG_MSI_LAPTOP=m +CONFIG_PANASONIC_LAPTOP=m +CONFIG_COMPAL_LAPTOP=m +CONFIG_SONY_LAPTOP=m +CONFIG_SONYPI_COMPAT=y +CONFIG_THINKPAD_ACPI=m +# CONFIG_THINKPAD_ACPI_DEBUGFACILITIES is not set +# CONFIG_THINKPAD_ACPI_DEBUG is not set +# CONFIG_THINKPAD_ACPI_UNSAFE_LEDS is not set +CONFIG_THINKPAD_ACPI_VIDEO=y +CONFIG_THINKPAD_ACPI_HOTKEY_POLL=y +CONFIG_INTEL_MENLOW=m +CONFIG_EEEPC_LAPTOP=m +CONFIG_ACPI_WMI=m +# CONFIG_ACPI_ASUS is not set +CONFIG_TOPSTAR_LAPTOP=m +CONFIG_ACPI_TOSHIBA=m + +# +# Firmware Drivers +# +CONFIG_EDD=m +# CONFIG_EDD_OFF is not set +CONFIG_FIRMWARE_MEMMAP=y +CONFIG_DELL_RBU=m +CONFIG_DCDBAS=m +CONFIG_DMIID=y +CONFIG_ISCSI_IBFT_FIND=y +CONFIG_ISCSI_IBFT=m + +# +# File systems +# +CONFIG_EXT2_FS=m +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=m +CONFIG_EXT3_DEFAULTS_TO_ORDERED=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_EXT4_FS=m +CONFIG_EXT4_FS_XATTR=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +# CONFIG_EXT4_DEBUG is not set +CONFIG_JBD=m +# CONFIG_JBD_DEBUG is not set +CONFIG_JBD2=m +# CONFIG_JBD2_DEBUG is not set +CONFIG_FS_MBCACHE=m +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +CONFIG_REISERFS_FS_XATTR=y +CONFIG_REISERFS_FS_POSIX_ACL=y +CONFIG_REISERFS_FS_SECURITY=y +CONFIG_JFS_FS=m +CONFIG_JFS_POSIX_ACL=y +CONFIG_JFS_SECURITY=y +# CONFIG_JFS_DEBUG is not set +CONFIG_JFS_STATISTICS=y +CONFIG_FS_POSIX_ACL=y +CONFIG_XFS_FS=m +CONFIG_XFS_QUOTA=y +CONFIG_XFS_POSIX_ACL=y +CONFIG_XFS_RT=y +# CONFIG_XFS_DEBUG is not set +CONFIG_GFS2_FS=m +# CONFIG_GFS2_FS_LOCKING_DLM is not set +CONFIG_OCFS2_FS=m +CONFIG_OCFS2_FS_O2CB=m +CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m +CONFIG_OCFS2_FS_STATS=y +CONFIG_OCFS2_DEBUG_MASKLOG=y +# CONFIG_OCFS2_DEBUG_FS is not set +# CONFIG_OCFS2_FS_POSIX_ACL is not set +CONFIG_BTRFS_FS=m +CONFIG_BTRFS_FS_POSIX_ACL=y +CONFIG_NILFS2_FS=m +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y +CONFIG_DNOTIFY=y +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_QUOTA=y +CONFIG_QUOTA_NETLINK_INTERFACE=y +CONFIG_PRINT_QUOTA_WARNING=y +CONFIG_QUOTA_TREE=m +CONFIG_QFMT_V1=m +CONFIG_QFMT_V2=m +CONFIG_QUOTACTL=y +CONFIG_AUTOFS_FS=m +CONFIG_AUTOFS4_FS=m +CONFIG_FUSE_FS=m +CONFIG_CUSE=m +CONFIG_GENERIC_ACL=y + +# +# Caches +# +CONFIG_FSCACHE=m +CONFIG_FSCACHE_STATS=y +# CONFIG_FSCACHE_HISTOGRAM is not set +# CONFIG_FSCACHE_DEBUG is not set +CONFIG_FSCACHE_OBJECT_LIST=y +CONFIG_CACHEFILES=m +# CONFIG_CACHEFILES_DEBUG is not set +# CONFIG_CACHEFILES_HISTOGRAM is not set + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_CONFIGFS_FS=m +CONFIG_MISC_FILESYSTEMS=y +CONFIG_ADFS_FS=m +CONFIG_ADFS_FS_RW=y +CONFIG_AFFS_FS=m +CONFIG_ECRYPT_FS=m +CONFIG_HFS_FS=m +CONFIG_HFSPLUS_FS=m +CONFIG_BEFS_FS=m +# CONFIG_BEFS_DEBUG is not set +CONFIG_BFS_FS=m +CONFIG_EFS_FS=m +CONFIG_JFFS2_FS=m +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +CONFIG_JFFS2_SUMMARY=y +CONFIG_JFFS2_FS_XATTR=y +CONFIG_JFFS2_FS_POSIX_ACL=y +CONFIG_JFFS2_FS_SECURITY=y +CONFIG_JFFS2_COMPRESSION_OPTIONS=y +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_JFFS2_CMODE_NONE is not set +CONFIG_JFFS2_CMODE_PRIORITY=y +# CONFIG_JFFS2_CMODE_SIZE is not set +# CONFIG_JFFS2_CMODE_FAVOURLZO is not set +CONFIG_UBIFS_FS=m +CONFIG_UBIFS_FS_XATTR=y +CONFIG_UBIFS_FS_ADVANCED_COMPR=y +CONFIG_UBIFS_FS_LZO=y +CONFIG_UBIFS_FS_ZLIB=y +# CONFIG_UBIFS_FS_DEBUG is not set +CONFIG_CRAMFS=m +CONFIG_SQUASHFS=m +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +CONFIG_VXFS_FS=m +CONFIG_MINIX_FS=m +CONFIG_OMFS_FS=m +CONFIG_HPFS_FS=m +CONFIG_QNX4FS_FS=m +CONFIG_ROMFS_FS=m +# CONFIG_ROMFS_BACKED_BY_BLOCK is not set +# CONFIG_ROMFS_BACKED_BY_MTD is not set +CONFIG_ROMFS_BACKED_BY_BOTH=y +CONFIG_ROMFS_ON_BLOCK=y +CONFIG_ROMFS_ON_MTD=y +CONFIG_SYSV_FS=m +CONFIG_UFS_FS=m +CONFIG_UFS_FS_WRITE=y +# CONFIG_UFS_DEBUG is not set +CONFIG_EXOFS_FS=m +# CONFIG_EXOFS_DEBUG is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +# CONFIG_NFS_V4_1 is not set +CONFIG_NFS_FSCACHE=y +CONFIG_NFSD=m +CONFIG_NFSD_V2_ACL=y +CONFIG_NFSD_V3=y +CONFIG_NFSD_V3_ACL=y +CONFIG_NFSD_V4=y +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +CONFIG_NFS_ACL_SUPPORT=m +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=m +CONFIG_SUNRPC_GSS=m +CONFIG_SUNRPC_XPRT_RDMA=m +CONFIG_RPCSEC_GSS_KRB5=m +CONFIG_RPCSEC_GSS_SPKM3=m +# CONFIG_SMB_FS is not set +CONFIG_CIFS=m +CONFIG_CIFS_STATS=y +CONFIG_CIFS_STATS2=y +CONFIG_CIFS_WEAK_PW_HASH=y +CONFIG_CIFS_UPCALL=y +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +# CONFIG_CIFS_DEBUG2 is not set +CONFIG_CIFS_DFS_UPCALL=y +CONFIG_CIFS_EXPERIMENTAL=y +CONFIG_NCP_FS=m +CONFIG_NCPFS_PACKET_SIGNING=y +CONFIG_NCPFS_IOCTL_LOCKING=y +CONFIG_NCPFS_STRONG=y +CONFIG_NCPFS_NFS_NS=y +CONFIG_NCPFS_OS2_NS=y +CONFIG_NCPFS_SMALLDOS=y +CONFIG_NCPFS_NLS=y +CONFIG_NCPFS_EXTRAS=y +CONFIG_CODA_FS=m +CONFIG_AFS_FS=m +# CONFIG_AFS_DEBUG is not set +CONFIG_AFS_FSCACHE=y +CONFIG_9P_FS=m +# CONFIG_9P_FSCACHE is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +CONFIG_OSF_PARTITION=y +# CONFIG_AMIGA_PARTITION is not set +CONFIG_ATARI_PARTITION=y +CONFIG_MAC_PARTITION=y +CONFIG_MSDOS_PARTITION=y +CONFIG_BSD_DISKLABEL=y +# CONFIG_MINIX_SUBPARTITION is not set +CONFIG_SOLARIS_X86_PARTITION=y +CONFIG_UNIXWARE_DISKLABEL=y +CONFIG_LDM_PARTITION=y +# CONFIG_LDM_DEBUG is not set +CONFIG_SGI_PARTITION=y +CONFIG_ULTRIX_PARTITION=y +CONFIG_SUN_PARTITION=y +CONFIG_KARMA_PARTITION=y +CONFIG_EFI_PARTITION=y +CONFIG_SYSV68_PARTITION=y +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=m +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_ASCII=m +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_NLS_UTF8=m +CONFIG_DLM=m +CONFIG_DLM_DEBUG=y + +# +# Kernel hacking +# +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_PRINTK_TIME=y +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=2048 +CONFIG_MAGIC_SYSRQ=y +CONFIG_STRIP_ASM_SYMS=y +CONFIG_UNUSED_SYMBOLS=y +CONFIG_DEBUG_FS=y +CONFIG_HEADERS_CHECK=y +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +# CONFIG_DETECT_SOFTLOCKUP is not set +CONFIG_DETECT_HUNG_TASK=y +# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set +CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 +CONFIG_SCHED_DEBUG=y +CONFIG_SCHEDSTATS=y +CONFIG_TIMER_STATS=y +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +CONFIG_STACKTRACE=y +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_HIGHMEM is not set +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_VIRTUAL is not set +# CONFIG_DEBUG_WRITECOUNT is not set +CONFIG_DEBUG_MEMORY_INIT=y +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set +CONFIG_ARCH_WANT_FRAME_POINTERS=y +CONFIG_FRAME_POINTER=y +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_KPROBES_SANITY_TEST is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +CONFIG_DEBUG_BLOCK_EXT_DEVT=y +CONFIG_DEBUG_FORCE_WEAK_PER_CPU=y +CONFIG_LKDTM=m +# CONFIG_FAULT_INJECTION is not set +CONFIG_LATENCYTOP=y +CONFIG_SYSCTL_SYSCALL_CHECK=y +# CONFIG_DEBUG_PAGEALLOC is not set +CONFIG_USER_STACKTRACE_SUPPORT=y +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_FP_TEST=y +CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_SYSCALL_TRACEPOINTS=y +CONFIG_RING_BUFFER=y +CONFIG_RING_BUFFER_ALLOW_SWAP=y +CONFIG_TRACING_SUPPORT=y +# CONFIG_FTRACE is not set +CONFIG_PROVIDE_OHCI1394_DMA_INIT=y +CONFIG_BUILD_DOCSRC=y +CONFIG_DYNAMIC_DEBUG=y +# CONFIG_DMA_API_DEBUG is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KMEMCHECK=y +# CONFIG_KMEMCHECK is not set +# CONFIG_STRICT_DEVMEM is not set +CONFIG_EARLY_PRINTK=y +CONFIG_EARLY_PRINTK_DBGP=y +# CONFIG_DEBUG_STACKOVERFLOW is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_PER_CPU_MAPS is not set +# CONFIG_X86_PTDUMP is not set +CONFIG_DEBUG_RODATA=y +# CONFIG_DEBUG_RODATA_TEST is not set +# CONFIG_DEBUG_NX_TEST is not set +# CONFIG_4KSTACKS is not set +# CONFIG_IOMMU_STRESS is not set +CONFIG_IO_DELAY_TYPE_0X80=0 +CONFIG_IO_DELAY_TYPE_0XED=1 +CONFIG_IO_DELAY_TYPE_UDELAY=2 +CONFIG_IO_DELAY_TYPE_NONE=3 +CONFIG_IO_DELAY_0X80=y +# CONFIG_IO_DELAY_0XED is not set +# CONFIG_IO_DELAY_UDELAY is not set +# CONFIG_IO_DELAY_NONE is not set +CONFIG_DEFAULT_IO_DELAY_TYPE=0 +CONFIG_OPTIMIZE_INLINING=y + +# +# Security options +# +CONFIG_KEYS=y +# CONFIG_KEYS_DEBUG_PROC_KEYS is not set +CONFIG_SECURITY=y +CONFIG_SECURITYFS=y +CONFIG_SECURITY_NETWORK=y +CONFIG_SECURITY_NETWORK_XFRM=y +CONFIG_SECURITY_PATH=y +CONFIG_SECURITY_FILE_CAPABILITIES=y +CONFIG_LSM_MMAP_MIN_ADDR=0 +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=0 +CONFIG_SECURITY_SELINUX_DISABLE=y +CONFIG_SECURITY_SELINUX_DEVELOP=y +CONFIG_SECURITY_SELINUX_AVC_STATS=y +CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1 +# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set +# CONFIG_SECURITY_SMACK is not set +# CONFIG_SECURITY_TOMOYO is not set +# CONFIG_IMA is not set +CONFIG_XOR_BLOCKS=m +CONFIG_ASYNC_CORE=m +CONFIG_ASYNC_MEMCPY=m +CONFIG_ASYNC_XOR=m +CONFIG_ASYNC_PQ=m +CONFIG_ASYNC_RAID6_RECOV=m +CONFIG_ASYNC_TX_DISABLE_PQ_VAL_DMA=y +CONFIG_ASYNC_TX_DISABLE_XOR_VAL_DMA=y +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +CONFIG_CRYPTO_FIPS=y +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD=m +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER=m +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG=m +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_PCOMP=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +CONFIG_CRYPTO_GF128MUL=m +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_WORKQUEUE=y +CONFIG_CRYPTO_CRYPTD=m +CONFIG_CRYPTO_AUTHENC=m +CONFIG_CRYPTO_TEST=m + +# +# Authenticated Encryption with Associated Data +# +CONFIG_CRYPTO_CCM=m +CONFIG_CRYPTO_GCM=m +CONFIG_CRYPTO_SEQIV=m + +# +# Block modes +# +CONFIG_CRYPTO_CBC=m +CONFIG_CRYPTO_CTR=m +CONFIG_CRYPTO_CTS=m +CONFIG_CRYPTO_ECB=m +CONFIG_CRYPTO_LRW=m +CONFIG_CRYPTO_PCBC=m +CONFIG_CRYPTO_XTS=m + +# +# Hash modes +# +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_XCBC=m +CONFIG_CRYPTO_VMAC=m + +# +# Digest +# +CONFIG_CRYPTO_CRC32C=m +CONFIG_CRYPTO_CRC32C_INTEL=m +CONFIG_CRYPTO_GHASH=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=m +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_RMD128=m +CONFIG_CRYPTO_RMD160=m +CONFIG_CRYPTO_RMD256=m +CONFIG_CRYPTO_RMD320=m +CONFIG_CRYPTO_SHA1=m +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_WP512=m + +# +# Ciphers +# +CONFIG_CRYPTO_AES=m +CONFIG_CRYPTO_AES_586=m +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_CAMELLIA=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_DES=m +CONFIG_CRYPTO_FCRYPT=m +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_SALSA20=m +CONFIG_CRYPTO_SALSA20_586=m +CONFIG_CRYPTO_SEED=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_TEA=m +# CONFIG_CRYPTO_TWOFISH is not set +CONFIG_CRYPTO_TWOFISH_COMMON=m +CONFIG_CRYPTO_TWOFISH_586=m + +# +# Compression +# +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_ZLIB=m +CONFIG_CRYPTO_LZO=m + +# +# Random Number Generation +# +CONFIG_CRYPTO_ANSI_CPRNG=m +CONFIG_CRYPTO_HW=y +CONFIG_CRYPTO_DEV_PADLOCK=m +CONFIG_CRYPTO_DEV_PADLOCK_AES=m +CONFIG_CRYPTO_DEV_PADLOCK_SHA=m +CONFIG_CRYPTO_DEV_GEODE=m +CONFIG_CRYPTO_DEV_HIFN_795X=m +CONFIG_CRYPTO_DEV_HIFN_795X_RNG=y +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_FIRST_BIT=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_GENERIC_FIND_LAST_BIT=y +CONFIG_CRC_CCITT=m +CONFIG_CRC16=m +CONFIG_CRC_T10DIF=m +CONFIG_CRC_ITU_T=m +CONFIG_CRC32=y +CONFIG_CRC7=m +CONFIG_LIBCRC32C=m +CONFIG_AUDIT_GENERIC=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=m +CONFIG_LZO_COMPRESS=m +CONFIG_LZO_DECOMPRESS=m +CONFIG_DECOMPRESS_GZIP=y +CONFIG_DECOMPRESS_BZIP2=y +CONFIG_DECOMPRESS_LZMA=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_REED_SOLOMON=m +CONFIG_REED_SOLOMON_DEC16=y +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_CHECK_SIGNATURE=y +CONFIG_NLATTR=y diff --git a/ipv6-no-autoconf b/ipv6-no-autoconf new file mode 100644 index 0000000..ad36da3 --- /dev/null +++ b/ipv6-no-autoconf @@ -0,0 +1,35 @@ +From: Olaf Kirch +Subject: Allow to bring up network interface w/o ipv6 autoconf +References: 161888 +Patch-mainline: no + +When bringing up a xen bridge device, it will always be configured to +use a MAC address of ff:ff:ff:ff:ff:fe. This greatly confuses IPv6 DAD, +which starts logging lots and lots of useless messages to syslog. + +We really want to disable IPv6 on these interfaces, and there doesn't +seem to be a reliable way to do this without bringing the interface +up first (and triggering IPv6 autoconf). + +This patch makes autoconf (DAD and router discovery) depend on the +interface's ability to do multicast. Turning off multicast for an +interface before bringing it up will suppress autoconfiguration. + +--- sle11sp1-2010-03-22.orig/net/ipv6/addrconf.c 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/net/ipv6/addrconf.c 2010-03-22 12:10:12.000000000 +0100 +@@ -2799,6 +2799,7 @@ static void addrconf_dad_start(struct in + spin_lock_bh(&ifp->lock); + + if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) || ++ !(dev->flags&IFF_MULTICAST) || + idev->cnf.accept_dad < 1 || + !(ifp->flags&IFA_F_TENTATIVE) || + ifp->flags & IFA_F_NODAD) { +@@ -2891,6 +2892,7 @@ static void addrconf_dad_completed(struc + if (ifp->idev->cnf.forwarding == 0 && + ifp->idev->cnf.rtr_solicits > 0 && + (dev->flags&IFF_LOOPBACK) == 0 && ++ (dev->flags & IFF_MULTICAST) && + (ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL)) { + /* + * If a host as already performed a random delay diff --git a/kbuild-really-dont-remove-bounds-asm-offsets-headers.patch b/kbuild-really-dont-remove-bounds-asm-offsets-headers.patch new file mode 100644 index 0000000..fcb7af2 --- /dev/null +++ b/kbuild-really-dont-remove-bounds-asm-offsets-headers.patch @@ -0,0 +1,62 @@ +Index: linux-2.6.30/Kbuild +=================================================================== +--- linux-2.6.30.orig/Kbuild ++++ linux-2.6.30/Kbuild +@@ -10,8 +10,8 @@ + + bounds-file := include/linux/bounds.h + +-always := $(bounds-file) +-targets := $(bounds-file) kernel/bounds.s ++always_noclean := $(bounds-file) ++targets := kernel/bounds.s + + quiet_cmd_bounds = GEN $@ + define cmd_bounds +@@ -45,8 +45,7 @@ $(obj)/$(bounds-file): kernel/bounds.s K + + offsets-file := include/asm/asm-offsets.h + +-always += $(offsets-file) +-targets += $(offsets-file) ++always_noclean += $(offsets-file) + targets += arch/$(SRCARCH)/kernel/asm-offsets.s + + +@@ -93,6 +92,3 @@ quiet_cmd_syscalls = CALL $< + PHONY += missing-syscalls + missing-syscalls: scripts/checksyscalls.sh FORCE + $(call cmd,syscalls) +- +-# Delete all targets during make clean +-clean-files := $(addprefix $(objtree)/,$(filter-out $(bounds-file) $(offsets-file),$(targets))) +Index: linux-2.6.30/scripts/Makefile.build +=================================================================== +--- linux-2.6.30.orig/scripts/Makefile.build ++++ linux-2.6.30/scripts/Makefile.build +@@ -15,6 +15,7 @@ obj-m := + lib-y := + lib-m := + always := ++always_noclean := + targets := + subdir-y := + subdir-m := +@@ -92,7 +93,7 @@ modorder-target := $(obj)/modules.order + + __build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \ + $(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) \ +- $(subdir-ym) $(always) ++ $(subdir-ym) $(always) $(always_noclean) + @: + + # Linus' kernel sanity checking tool +@@ -264,7 +265,7 @@ $(obj)/%.o: $(src)/%.S FORCE + $(call if_changed_dep,as_o_S) + + targets += $(real-objs-y) $(real-objs-m) $(lib-y) +-targets += $(extra-y) $(MAKECMDGOALS) $(always) ++targets += $(extra-y) $(MAKECMDGOALS) $(always) $(always_noclean) + + # Linker scripts preprocessor (.lds.S -> .lds) + # --------------------------------------------------------------------------- diff --git a/kernel-xen.spec b/kernel-xen.spec new file mode 100644 index 0000000..24a495e --- /dev/null +++ b/kernel-xen.spec @@ -0,0 +1,504 @@ +%define name kernel-xen +%define version 2.6.32.11 +%define rel 2 +%define kernel_version 2.6.32.11 +%define kernel_extraversion xen-%{rel}mdv +# ensures file uniqueness +%define kernel_file_string %{kernel_version}-%{kernel_extraversion} +# ensures package uniqueness +%define kernel_package_string %{kernel_version}-%{rel}mdv +%define kernel_source_dir %{_prefix}/src/%{name}-%{kernel_package_string} +%define kernel_devel_dir %{_prefix}/src/%{name}-devel-%{kernel_package_string} + +%define _default_patch_fuzz 3 + +%ifarch %ix86 +%define config %{SOURCE1} +%endif +%ifarch x86_64 +%define config %{SOURCE2} +%endif + +Name: %{name} +Version: %{version} +Release: %mkrel %{rel} +Summary: The Xen kernel +Group: System/Kernel and hardware +License: GPL +Source0: linux-%{kernel_version}.tar.bz2 +Source1: i386_defconfig-server +Source2: x86_64_defconfig-server + +Source12: disable-mrproper-in-devel-rpms.patch +Source13: kbuild-really-dont-remove-bounds-asm-offsets-headers.patch +# suze patches +Patch90: bug-561933_uv_pat_is_gru_range.patch +Patch91: x86-Unify-fixup_irqs-for-32-bit-and-64-bit-kernels.patch +Patch92: SoN-23-mm-swapfile.patch +Patch93: x86-cpu-mv-display_cacheinfo-cpu_detect_cache_sizes.patch +Patch94: fix_clock_gettime_vsyscall_time_warp.diff +### both uml framebuffer and xen need this one. +Patch100: add-console-use-vt +# split out patches +Patch101: linux-2.6.19-rc1-kexec-move_segment_code-i386.patch +Patch102: linux-2.6.19-rc1-kexec-move_segment_code-x86_64.patch +Patch103: ipv6-no-autoconf +Patch104: pci-guestdev +Patch105: pci-reserve +Patch106: sfc-driverlink +Patch107: sfc-resource-driver +Patch108: sfc-driverlink-conditional +Patch109: sfc-external-sram +Patch110: tmem +# bulk stuff, new files for xen +Patch200: xen3-auto-xen-arch.diff +Patch201: xen3-auto-xen-drivers.diff +Patch202: xen3-auto-include-xen-interface.diff +# kconfig bits for xen +Patch300: xen3-auto-xen-kconfig.diff +# common code changes +Patch400: xen3-auto-common.diff +Patch401: xen3-auto-arch-x86.diff +Patch402: xen3-auto-arch-i386.diff +Patch403: xen3-auto-arch-x86_64.diff +# fixups due to upstream Xen parts +Patch500: xen3-fixup-xen +Patch501: sfc-set-arch +Patch502: sfc-endianness +# newer changeset backports +# changes outside arch/{i386,x86_64}/xen +Patch700: xen3-fixup-kconfig +Patch701: xen3-fixup-common +Patch702: xen3-fixup-arch-x86 +# ports of other patches +Patch800: xen3-patch-2.6.18 +Patch801: xen3-patch-2.6.19 +Patch802: xen3-patch-2.6.20 +Patch803: xen3-patch-2.6.21 +Patch804: xen3-patch-2.6.22 +Patch805: xen3-patch-2.6.23 +Patch806: xen3-patch-2.6.24 +Patch807: xen3-patch-2.6.25 +Patch808: xen3-patch-2.6.26 +Patch809: xen3-patch-2.6.27 +Patch810: xen3-patch-2.6.28 +Patch811: xen3-patch-2.6.29 +Patch812: xen3-patch-2.6.30 +Patch813: xen3-patch-2.6.31 +Patch814: xen3-patch-2.6.32 +Patch815: xen3-patch-2.6.32.1-2 +Patch816: xen3-patch-2.6.32.2-3 +Patch817: xen3-patch-2.6.32.3-4 +Patch818: xen3-patch-2.6.32.7-8 +Patch819: xen3-patch-2.6.32.8-9 +Patch820: xen3-patch-2.6.32.9-10 +Patch821: xen3-seccomp-disable-tsc-option +Patch822: xen3-fix_clock_gettime_vsyscall_time_warp.diff +Patch823: xen3-x86-mcp51-no-dac +#Patch824: xen3-x86-64-preserve-large-page-mapping-for-1st-2mb-kernel-txt-with-config_debug_rodata +#Patch825: xen3-x86-64-align-rodata-kernel-section-to-2mb-with-config_debug_rodata +#Patch826: xen3-x86-mark_rodata_rw.patch +#Patch827: xen3-x86-ftrace-fix-rodata-1.patch +#Patch828: xen3-x86-ftrace-fix-rodata-3.patch +Patch829: xen3-x86-Remove-CPU-cache-size-output-for-non-Intel-too.patch +Patch830: xen3-x86-cpu-mv-display_cacheinfo-cpu_detect_cache_sizes.patch +Patch831: xen3-x86-Limit-the-number-of-processor-bootup-messages.patch +Patch832: xen3-x86_64_apic_consider_hotplug_for_mode_logical_flat.patch +Patch833: xen3-x86_ioapic_fix_out_of_order_gsi.patch +Patch834: xen3-x86-Reduce-per-cpu-warning-boot-up-messages.patch +Patch835: xen3-x86-pat-Update-page-flags-for-memtype-without-using-memtype_lock-V4.patch +Patch836: xen3-bug-561933_uv_pat_is_gru_range.patch +Patch837: xen3-x86-Fix-sched_clock_cpu-for-systems-with-unsynchronized-TSC.patch +Patch838: xen3-x86-Unify-fixup_irqs-for-32-bit-and-64-bit-kernels.patch +Patch839: xen3-x86-intr-remap-Avoid-irq_chip-mask-unmask-in-fixup_irqs-for-intr-remapping.patch +Patch840: xen3-x86-Remove-local_irq_enable-local_irq_disable-in-fixup_irqs.patch +#Patch841: xen3-vmw_pvscsi-scsi-driver-for-vmware-s-virtual-hba.patch +#Patch842: xen3-add-support-for-intel-cougar-point-chipset.patch +#Patch843: xen3-kdb-x86 +Patch844: xen3-stack-unwind +Patch845: xen3-x86_64-unwind-annotations +# bugfixes and enhancements +Patch900: xen-balloon-max-target +Patch901: xen-modular-blktap +Patch902: xen-blkback-bimodal-suse +Patch903: xen-blkif-protocol-fallback-hack +Patch904: xen-blkback-cdrom +Patch905: xen-blktap-write-barriers +Patch906: xen-op-packet +Patch907: xen-blkfront-cdrom +Patch908: xen-sections +Patch909: xen-swiotlb-heuristics +Patch910: xen-kconfig-compat +Patch911: xen-cpufreq-report +Patch912: xen-staging-build +Patch913: xen-sysdev-suspend +Patch914: xen-ipi-per-cpu-irq +Patch915: xen-virq-per-cpu-irq +Patch916: xen-spinlock-poll-early +Patch917: xen-configurable-guest-devices +Patch918: xen-netback-nr-irqs +Patch919: xen-netback-notify-multi +Patch920: xen-netback-generalize +Patch921: xen-netback-multiple-tasklets +Patch922: xen-netback-kernel-threads +Patch923: xen-netfront-ethtool +Patch924: xen-unpriv-build +Patch925: xen-dcdbas +Patch926: xen-floppy +Patch927: xen-x86-panic-no-reboot +Patch928: xen-x86-dcr-fallback +Patch929: xen-x86-consistent-nmi +Patch930: xen-x86-no-lapic +Patch931: xen-x86-pmd-handling +Patch932: xen-x86-bigmem +Patch933: xen-x86-machphys-prediction +Patch934: xen-x86-exit-mmap +Patch935: xen-x86-per-cpu-vcpu-info +Patch936: xen-x86-xtime-lock +Patch937: xen-x86-time-per-cpu +Patch938: xen-x86_64-pgd-pin +Patch939: xen-x86_64-pgd-alloc-order +Patch940: xen-x86_64-dump-user-pgt +Patch941: xen-x86_64-note-init-p2m +BuildRoot: %{_tmppath}/%{name}-%{version} + +%description +The XEN kernel. + +%package -n kernel-xen-%{kernel_package_string} +Version: 1 +Release: %mkrel 1 +Summary: XEN kernel +Group: System/Kernel and hardware +Provides: kernel = %{kernel_version} +Provides: kernel-xen = %{kernel_version} +Requires(post): bootloader-utils mkinitrd xen-hypervisor +Requires(postun): bootloader-utils + +%description -n kernel-xen-%{kernel_package_string} +The XEN kernel. + +%package devel-%{kernel_package_string} +Version: 1 +Release: %mkrel 1 +Summary: XEN kernel devel files +Group: System/Kernel and hardware +Provides: kernel-devel = %{kernel_version} +Autoreqprov: no + +%description devel-%{kernel_package_string} +This package contains the kernel-devel files that should be enough to build +3rdparty drivers against for use with the %{kname}-%{buildrel}. + +%package source-%{kernel_package_string} +Version: 1 +Release: %mkrel 1 +Summary: XEN kernel sources +Group: System/Kernel and hardware +Provides: kernel-source = %{kernel_version} +Autoreqprov: no + +%description source-%{kernel_package_string} +This package contains the source code files for the Linux +kernel. Theese source files are only needed if you want to build your own +custom kernel that is better tuned to your particular hardware. + +%package debug-%{kernel_package_string} +Version: 1 +Release: %mkrel 1 +Summary: Xen kernel debug files +Group: Development/Debug +Requires: glibc-devel +Provides: kernel-debug = %{kernel_version} +Autoreqprov: no + +%description debug-%{kernel_package_string} +This package contains the kernel-debug files that should be enough to +use debugging/monitoring tool (like systemtap, oprofile, ...) + +%package doc-%{kernel_package_string} +Version: 1 +Release: %mkrel 1 +Summary: XEN kernel documentation +Group: System/Kernel and hardware +Autoreqprov: no + +%description doc-%{kernel_package_string} +This package contains documentation files form the kernel source. Various +bits of information about the Linux kernel and the device drivers shipped +with it are documented in these files. You also might want install this +package if you need a reference to the options that can be passed to Linux +kernel modules at load time. + +%prep +%setup -q -n linux-%{kernel_version} +%apply_patches + +%build +perl -p \ + -e 's/CONFIG_LOCALVERSION=.*/CONFIG_LOCALVERSION="-%{kernel_extraversion}"/' \ + < %config > .config +%make oldconfig +%make +%make modules + +%install +rm -rf %{buildroot} +install -d -m 755 %{buildroot}/boot +install -m 644 System.map %{buildroot}/boot/System.map-%{kernel_file_string} +install -m 644 .config %{buildroot}/boot/config-%{kernel_file_string} +install -m 644 arch/x86/boot/vmlinuz \ + %{buildroot}/boot/vmlinuz-%{kernel_file_string} + +# modules +%make modules_install INSTALL_MOD_PATH=%{buildroot} + +# remove firmwares +rm -rf %{buildroot}/lib/firmware + +# remove symlinks +rm -f %{buildroot}/lib/modules/%{kernel_file_string}/build +rm -f %{buildroot}/lib/modules/%{kernel_file_string}/source + +# strip modules, as spec-helper won't recognize them once compressed +find %{buildroot}/lib/modules/%{kernel_file_string}/kernel -name *.ko \ + -exec objcopy --only-keep-debug '{}' '{}'.debug \; +find %{buildroot}/lib/modules/%{kernel_file_string}/kernel -name *.ko \ + -exec objcopy --add-gnu-debuglink='{}'.debug --strip-debug '{}' \; +find %{buildroot}/lib/modules/%{kernel_file_string}/kernel -name *.ko.debug | \ + sed -e 's|%{buildroot}||' > kernel_debug_files.list + +# create an exclusion list for those debug files +sed -e 's|^|%exclude |' < kernel_debug_files.list > no_kernel_debug_files.list + +# compress modules +find %{buildroot}/lib/modules/%{kernel_file_string} -name *.ko | xargs gzip -9 +/sbin/depmod -u -ae -b %{buildroot} -r \ + -F %{buildroot}/boot/System.map-%{kernel_file_string} \ + %{kernel_file_string} + +# create modules description +pushd %{buildroot}/lib/modules/%{kernel_file_string} +find . -name *.ko.gz | xargs /sbin/modinfo | \ + perl -lne 'print "$name\t$1" if $name && /^description:\s*(.*)/; $name = $1 if m!^filename:\s*(.*)\.k?o!; $name =~ s!.*/!!' \ + > modules.description +popd + +# install kernel sources +install -d -m 755 %{buildroot}%{kernel_source_dir} +tar cf - . \ + --exclude '*.o' --exclude '*.ko' --exclude '*.cmd' \ + --exclude '.temp*' --exclude '.tmp*' --exclude '*.0[0-9][0-9][0-9]' \ + --exclude modules.order --exclude .gitignore \ + | tar xf - -C %{buildroot}%{kernel_source_dir} +chmod -R a+rX %{buildroot}%{kernel_source_dir} + +# we remove all the source files that we don't ship +# first architecture files +for i in alpha arm arm26 avr32 blackfin cris frv h8300 ia64 microblaze mips \ + m32r m68k m68knommu mn10300 parisc powerpc ppc s390 sh sh64 sparc v850 xtensa; do + rm -rf %{buildroot}%{kernel_source_dir}/arch/$i + rm -rf %{buildroot}%{kernel_source_dir}/include/asm-$i +done + +%ifnarch %{ix86} x86_64 + rm -rf %{buildroot}%{kernel_source_dir}/arch/x86 + rm -rf %{buildroot}%{kernel_source_dir}/include/asm-x86 +%endif + +rm -rf %{buildroot}%{kernel_source_dir}/vmlinux +rm -rf %{buildroot}%{kernel_source_dir}/System.map +rm -rf %{buildroot}%{kernel_source_dir}/Module.* +rm -rf %{buildroot}%{kernel_source_dir}/*.list +rm -rf %{buildroot}%{kernel_source_dir}/.config.* +rm -rf %{buildroot}%{kernel_source_dir}/.missing-syscalls.d +rm -rf %{buildroot}%{kernel_source_dir}/.version +rm -rf %{buildroot}%{kernel_source_dir}/.mailmap + +# install devel files +install -d -m 755 %{buildroot}%{kernel_devel_dir} +for i in $(find . -name 'Makefile*'); do + cp -R --parents $i %{buildroot}%{kernel_devel_dir}; +done +for i in $(find . -name 'Kconfig*' -o -name 'Kbuild*'); do + cp -R --parents $i %{buildroot}%{kernel_devel_dir}; +done +cp -fR include %{buildroot}%{kernel_devel_dir} +cp -fR scripts %{buildroot}%{kernel_devel_dir} +%ifarch %{ix86} x86_64 + cp -fR arch/x86/kernel/asm-offsets.{c,s} \ + %{buildroot}%{kernel_devel_dir}/arch/x86/kernel/ + cp -fR arch/x86/kernel/asm-offsets_{32,64}.c \ + %{buildroot}%{kernel_devel_dir}/arch/x86/kernel/ + cp -fR arch/x86/include %{buildroot}%{kernel_devel_dir}/arch/x86/ +%else + cp -fR arch/%{target_arch}/kernel/asm-offsets.{c,s} \ + %{buildroot}%{kernel_devel_dir}/arch/%{target_arch}/kernel/ + cp -fR arch/%{target_arch}/include \ + %{buildroot}%{kernel_devel_dir}/arch/%{target_arch}/ +%endif +cp -fR .config Module.symvers %{buildroot}%{kernel_devel_dir} + +# Needed for truecrypt build (Danny) +cp -fR drivers/md/dm.h %{buildroot}%{kernel_devel_dir}/drivers/md/ + +# Needed for external dvb tree (#41418) +cp -fR drivers/media/dvb/dvb-core/*.h \ + %{buildroot}%{kernel_devel_dir}/drivers/media/dvb/dvb-core/ +cp -fR drivers/media/dvb/frontends/lgdt330x.h \ + %{buildroot}%{kernel_devel_dir}/drivers/media/dvb/frontends/ + +# add acpica header files, needed for fglrx build +cp -fR drivers/acpi/acpica/*.h \ + %{buildroot}%{kernel_devel_dir}/drivers/acpi/acpica/ + +# disable mrproper +patch -p1 -d %{buildroot}%{kernel_devel_dir} -i %{SOURCE12} + +# disable bounds.h and asm-offsets.h removal +patch -p1 -d %{buildroot}%{kernel_devel_dir} -i %{SOURCE13} + +%post %{kernel_package_string} +/sbin/installkernel %{kernel_file_string} +pushd /boot > /dev/null +if [ -L vmlinuz-xen ]; then + rm -f vmlinuz-xen +fi +ln -sf vmlinuz-%{kernel_file_string} vmlinuz-xen +if [ -L initrd-xen.img ]; then + rm -f initrd-xen.img +fi +ln -sf initrd-%{kernel_file_string}.img initrd-xen.img +popd > /dev/null + +%postun %{kernel_package_string} +/sbin/installkernel -R %{kernel_file_string} +pushd /boot > /dev/null +if [ -L vmlinuz-xen ]; then + if [ "$(readlink vmlinuz-xen)" = "vmlinuz-%{kernel_file_string}" ]; then + rm -f vmlinuz-xen + fi +fi +if [ -L initrd-xen.img ]; then + if [ "$(readlink initrd-xen.img)" = "initrd-%{kernel_file_string}.img" ]; then + rm -f initrd-xen.img + fi +fi +popd > /dev/null + +%post devel-%{kernel_package_string} +if [ -d /lib/modules/%{kernel_file_string} ]; then + ln -sf %{kernel_devel_dir} /lib/modules/%{kernel_file_string}/build + ln -sf %{kernel_devel_dir} /lib/modules/%{kernel_file_string}/source +fi + +%preun devel-%{kernel_package_string} +if [ -L /lib/modules/%{kernel_file_string}/build ]; then + rm -f /lib/modules/%{kernel_devel_string}/build +fi +if [ -L /lib/modules/%{kernel_file_string}/source ]; then + rm -f /lib/modules/%{kernel_devel_string}/source +fi + +%post source-%{kernel_package_string} +if [ -d /lib/modules/%{kernel_file_string} ]; then + ln -sf %{kernel_source_dir} /lib/modules/%{kernel_file_string}/build + ln -sf %{kernel_source_dir} /lib/modules/%{kernel_file_string}/source +fi + +%preun source-%{kernel_package_string} +if [ -L /lib/modules/%{kernel_file_string}/build ]; then + rm -f /lib/modules/%{kernel_source_string}/build +fi +if [ -L /lib/modules/%{kernel_file_string}/source ]; then + rm -f /lib/modules/%{kernel_source_string}/source +fi + +%clean +rm -rf %{buildroot} + +%files -n kernel-xen-%{kernel_package_string} -f no_kernel_debug_files.list +%defattr(-,root,root) +/lib/modules/%{kernel_file_string} +/boot/System.map-%{kernel_file_string} +/boot/config-%{kernel_file_string} +/boot/vmlinuz-%{kernel_file_string} + +%files -n kernel-xen-devel-%{kernel_package_string} +%defattr(-,root,root) +%{kernel_devel_dir} + +%files -n kernel-xen-source-%{kernel_package_string} +%defattr(-,root,root) +%{kernel_source_dir} +%exclude %{kernel_source_dir}/Documentation + +%files -n kernel-xen-doc-%{kernel_package_string} +%defattr(-,root,root) +%{kernel_source_dir}/Documentation + +%files -n kernel-xen-debug-%{kernel_package_string} -f kernel_debug_files.list +%defattr(-,root,root) + + +%changelog +* Mon Apr 05 2010 Guillaume Rousse 2.6.32.11-2mdv2010.1 ++ Revision: 531739 +- exclude patch backup files from sources + +* Sun Apr 04 2010 Guillaume Rousse 2.6.32.11-1mdv2010.1 ++ Revision: 531429 +- switch to Suze SLE11-SP1 branch, for easier maintainance +- revert to 2.6.32 +- new version + +* Mon Mar 15 2010 Guillaume Rousse 2.6.33-1mdv2010.1 ++ Revision: 519112 +- new version +- switch to 2.6.31.12 +- sync configuration with default kernel-server +- new kernel version +- new patchset +- set fuziness level to 2, it's too painful to rediff patches + +* Sat Nov 07 2009 Guillaume Rousse 2.6.30.2-7mdv2010.1 ++ Revision: 462699 +- standard -devel, -source and -doc packages +- ensure kernel-devel contains actual sources of this kernel, not just vanilla + sources +- kernel-devel doesn't require kernel itself + +* Wed Oct 14 2009 Pascal Terjan 2.6.30.2-6mdv2010.0 ++ Revision: 457357 +- We need xen-hypervisor, not xen +- Create unversioned links +- Require(post) xen, else bootloader config gets wrong +- Removes bootloader entries on removal +- Create unversioned links in /boot +- Require bootloader-utils and mkinitrd for post + +* Thu Oct 08 2009 Guillaume Rousse 2.6.30.2-5mdv2010.0 ++ Revision: 456092 +- don't ship kernel modules debug files in main kernel (spotted by buchan) + +* Thu Oct 01 2009 Guillaume Rousse 2.6.30.2-4mdv2010.0 ++ Revision: 452315 +- fix build with gcc 4.3 + +* Thu Oct 01 2009 Guillaume Rousse 2.6.30.2-3mdv2010.0 ++ Revision: 452224 +- install files manually, 'make install' is too much fragile + +* Sat Sep 26 2009 Guillaume Rousse 2.6.30.2-2mdv2010.0 ++ Revision: 449505 +- don't use parallel make invocation for installation +- post-installation initrd and bootloader handling +- drop %%apply_patch macro, it's not backportable + +* Tue Sep 01 2009 Pascal Terjan 2.6.30.2-1mdv2010.0 ++ Revision: 423653 +- version files in /boot + + + Guillaume Rousse + - import kernel-xen + diff --git a/linux-2.6.19-rc1-kexec-move_segment_code-i386.patch b/linux-2.6.19-rc1-kexec-move_segment_code-i386.patch new file mode 100644 index 0000000..64b80a4 --- /dev/null +++ b/linux-2.6.19-rc1-kexec-move_segment_code-i386.patch @@ -0,0 +1,155 @@ +Subject: kexec: Move asm segment handling code to the assembly file (i386) +From: http://xenbits.xensource.com/xen-unstable.hg (tip 13816) +Patch-mainline: obsolete + +This patch moves the idt, gdt, and segment handling code from machine_kexec.c +to relocate_kernel.S. The main reason behind this move is to avoid code +duplication in the Xen hypervisor. With this patch all code required to kexec +is put on the control page. + +On top of that this patch also counts as a cleanup - I think it is much +nicer to write assembly directly in assembly files than wrap inline assembly +in C functions for no apparent reason. + +Signed-off-by: Magnus Damm +Acked-by: jbeulich@novell.com + + Applies to 2.6.19-rc1. + jb: fixed up register usage (paralleling what's needed for 2.6.30 on x86-64) + +--- head-2009-10-06.orig/arch/x86/kernel/machine_kexec_32.c 2009-10-12 10:33:15.000000000 +0200 ++++ head-2009-10-06/arch/x86/kernel/machine_kexec_32.c 2009-04-21 10:33:15.000000000 +0200 +@@ -26,48 +26,6 @@ + #include + #include + +-static void set_idt(void *newidt, __u16 limit) +-{ +- struct desc_ptr curidt; +- +- /* ia32 supports unaliged loads & stores */ +- curidt.size = limit; +- curidt.address = (unsigned long)newidt; +- +- load_idt(&curidt); +-} +- +- +-static void set_gdt(void *newgdt, __u16 limit) +-{ +- struct desc_ptr curgdt; +- +- /* ia32 supports unaligned loads & stores */ +- curgdt.size = limit; +- curgdt.address = (unsigned long)newgdt; +- +- load_gdt(&curgdt); +-} +- +-static void load_segments(void) +-{ +-#define __STR(X) #X +-#define STR(X) __STR(X) +- +- __asm__ __volatile__ ( +- "\tljmp $"STR(__KERNEL_CS)",$1f\n" +- "\t1:\n" +- "\tmovl $"STR(__KERNEL_DS)",%%eax\n" +- "\tmovl %%eax,%%ds\n" +- "\tmovl %%eax,%%es\n" +- "\tmovl %%eax,%%fs\n" +- "\tmovl %%eax,%%gs\n" +- "\tmovl %%eax,%%ss\n" +- : : : "eax", "memory"); +-#undef STR +-#undef __STR +-} +- + static void machine_kexec_free_page_tables(struct kimage *image) + { + free_page((unsigned long)image->arch.pgd); +@@ -228,24 +186,6 @@ void machine_kexec(struct kimage *image) + page_list[PA_SWAP_PAGE] = (page_to_pfn(image->swap_page) + << PAGE_SHIFT); + +- /* +- * The segment registers are funny things, they have both a +- * visible and an invisible part. Whenever the visible part is +- * set to a specific selector, the invisible part is loaded +- * with from a table in memory. At no other time is the +- * descriptor table in memory accessed. +- * +- * I take advantage of this here by force loading the +- * segments, before I zap the gdt with an invalid value. +- */ +- load_segments(); +- /* +- * The gdt & idt are now invalid. +- * If you want to load them you must set up your own idt & gdt. +- */ +- set_gdt(phys_to_virt(0), 0); +- set_idt(phys_to_virt(0), 0); +- + /* now call it */ + image->start = relocate_kernel_ptr((unsigned long)image->head, + (unsigned long)page_list, +--- head-2009-10-06.orig/arch/x86/kernel/relocate_kernel_32.S 2009-10-12 10:33:15.000000000 +0200 ++++ head-2009-10-06/arch/x86/kernel/relocate_kernel_32.S 2009-10-12 10:39:36.000000000 +0200 +@@ -87,14 +87,32 @@ relocate_kernel: + movl PTR(PA_PGD)(%ebp), %eax + movl %eax, %cr3 + ++ /* setup idt */ ++ lidtl idt_48 - relocate_kernel(%edi) ++ ++ /* setup gdt */ ++ leal gdt - relocate_kernel(%edi), %eax ++ movl %eax, (gdt_48 - relocate_kernel) + 2(%edi) ++ lgdtl gdt_48 - relocate_kernel(%edi) ++ ++ /* setup data segment registers */ ++ mov $(gdt_ds - gdt), %eax ++ mov %eax, %ds ++ mov %eax, %es ++ mov %eax, %fs ++ mov %eax, %gs ++ mov %eax, %ss ++ + /* setup a new stack at the end of the physical control page */ + lea PAGE_SIZE(%edi), %esp + +- /* jump to identity mapped page */ ++ /* load new code segment and jump to identity mapped page */ ++ pushl $0 ++ pushl $(gdt_cs - gdt) + movl %edi, %eax + addl $(identity_mapped - relocate_kernel), %eax + pushl %eax +- ret ++ iretl + + identity_mapped: + /* store the start address on the stack */ +@@ -271,5 +289,22 @@ swap_pages: + popl %ebp + ret + ++ .align 16 ++gdt: ++ .quad 0x0000000000000000 /* NULL descriptor */ ++gdt_cs: ++ .quad 0x00cf9a000000ffff /* kernel 4GB code at 0x00000000 */ ++gdt_ds: ++ .quad 0x00cf92000000ffff /* kernel 4GB data at 0x00000000 */ ++gdt_end: ++ ++gdt_48: ++ .word gdt_end - gdt - 1 /* limit */ ++ .long 0 /* base - filled in by code above */ ++ ++idt_48: ++ .word 0 /* limit */ ++ .long 0 /* base */ ++ + .globl kexec_control_code_size + .set kexec_control_code_size, . - relocate_kernel diff --git a/linux-2.6.19-rc1-kexec-move_segment_code-x86_64.patch b/linux-2.6.19-rc1-kexec-move_segment_code-x86_64.patch new file mode 100644 index 0000000..cbf66fc --- /dev/null +++ b/linux-2.6.19-rc1-kexec-move_segment_code-x86_64.patch @@ -0,0 +1,150 @@ +Subject: kexec: Move asm segment handling code to the assembly file (x86_64) +From: http://xenbits.xensource.com/xen-unstable.hg (tip 13816) +Patch-mainline: obsolete + +This patch moves the idt, gdt, and segment handling code from machine_kexec.c +to relocate_kernel.S. The main reason behind this move is to avoid code +duplication in the Xen hypervisor. With this patch all code required to kexec +is put on the control page. + +On top of that this patch also counts as a cleanup - I think it is much +nicer to write assembly directly in assembly files than wrap inline assembly +in C functions for no apparent reason. + +Signed-off-by: Magnus Damm +Acked-by: jbeulich@novell.com + + Applies to 2.6.19-rc1. + jb: fixed up register usage for 2.6.30 (bnc#545206) + +--- head-2009-10-06.orig/arch/x86/kernel/machine_kexec_64.c 2009-10-12 10:17:22.000000000 +0200 ++++ head-2009-10-06/arch/x86/kernel/machine_kexec_64.c 2009-04-21 10:35:13.000000000 +0200 +@@ -201,47 +201,6 @@ static int init_pgtable(struct kimage *i + return init_transition_pgtable(image, level4p); + } + +-static void set_idt(void *newidt, u16 limit) +-{ +- struct desc_ptr curidt; +- +- /* x86-64 supports unaliged loads & stores */ +- curidt.size = limit; +- curidt.address = (unsigned long)newidt; +- +- __asm__ __volatile__ ( +- "lidtq %0\n" +- : : "m" (curidt) +- ); +-}; +- +- +-static void set_gdt(void *newgdt, u16 limit) +-{ +- struct desc_ptr curgdt; +- +- /* x86-64 supports unaligned loads & stores */ +- curgdt.size = limit; +- curgdt.address = (unsigned long)newgdt; +- +- __asm__ __volatile__ ( +- "lgdtq %0\n" +- : : "m" (curgdt) +- ); +-}; +- +-static void load_segments(void) +-{ +- __asm__ __volatile__ ( +- "\tmovl %0,%%ds\n" +- "\tmovl %0,%%es\n" +- "\tmovl %0,%%ss\n" +- "\tmovl %0,%%fs\n" +- "\tmovl %0,%%gs\n" +- : : "a" (__KERNEL_DS) : "memory" +- ); +-} +- + int machine_kexec_prepare(struct kimage *image) + { + unsigned long start_pgtable; +@@ -308,24 +267,6 @@ void machine_kexec(struct kimage *image) + page_list[PA_SWAP_PAGE] = (page_to_pfn(image->swap_page) + << PAGE_SHIFT); + +- /* +- * The segment registers are funny things, they have both a +- * visible and an invisible part. Whenever the visible part is +- * set to a specific selector, the invisible part is loaded +- * with from a table in memory. At no other time is the +- * descriptor table in memory accessed. +- * +- * I take advantage of this here by force loading the +- * segments, before I zap the gdt with an invalid value. +- */ +- load_segments(); +- /* +- * The gdt & idt are now invalid. +- * If you want to load them you must set up your own idt & gdt. +- */ +- set_gdt(phys_to_virt(0), 0); +- set_idt(phys_to_virt(0), 0); +- + /* now call it */ + image->start = relocate_kernel((unsigned long)image->head, + (unsigned long)page_list, +--- head-2009-10-06.orig/arch/x86/kernel/relocate_kernel_64.S 2009-10-12 10:17:22.000000000 +0200 ++++ head-2009-10-06/arch/x86/kernel/relocate_kernel_64.S 2009-10-12 10:32:00.000000000 +0200 +@@ -91,13 +91,30 @@ relocate_kernel: + /* Switch to the identity mapped page tables */ + movq %r9, %cr3 + ++ /* setup idt */ ++ lidtq idt_80 - relocate_kernel(%r8) ++ ++ /* setup gdt */ ++ leaq gdt - relocate_kernel(%r8), %rax ++ movq %rax, (gdt_80 - relocate_kernel) + 2(%r8) ++ lgdtq gdt_80 - relocate_kernel(%r8) ++ ++ /* setup data segment registers */ ++ xorl %eax, %eax ++ movl %eax, %ds ++ movl %eax, %es ++ movl %eax, %fs ++ movl %eax, %gs ++ movl %eax, %ss ++ + /* setup a new stack at the end of the physical control page */ + lea PAGE_SIZE(%r8), %rsp + +- /* jump to identity mapped page */ ++ /* load new code segment and jump to identity mapped page */ + addq $(identity_mapped - relocate_kernel), %r8 ++ pushq $(gdt_cs - gdt) + pushq %r8 +- ret ++ lretq + + identity_mapped: + /* store the start address on the stack */ +@@ -262,5 +279,20 @@ swap_pages: + 3: + ret + ++ .align 16 ++gdt: ++ .quad 0x0000000000000000 /* NULL descriptor */ ++gdt_cs: ++ .quad 0x00af9a000000ffff ++gdt_end: ++ ++gdt_80: ++ .word gdt_end - gdt - 1 /* limit */ ++ .quad 0 /* base - filled in by code above */ ++ ++idt_80: ++ .word 0 /* limit */ ++ .quad 0 /* base */ ++ + .globl kexec_control_code_size + .set kexec_control_code_size, . - relocate_kernel diff --git a/pci-guestdev b/pci-guestdev new file mode 100644 index 0000000..9ec70f9 --- /dev/null +++ b/pci-guestdev @@ -0,0 +1,2645 @@ +Subject: xen/dom0: Reserve devices for guest use +From: http://xenbits.xensource.com/linux-2.6.18-xen.hg (tip 898:ca12928cdafe) +Patch-mainline: obsolete + +jb: Added support for reassign_resources=all (bnc#574224). +Acked-by: jbeulich@novell.com + +--- sle11sp1-2010-03-22.orig/Documentation/kernel-parameters.txt 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/Documentation/kernel-parameters.txt 2010-03-11 09:11:45.000000000 +0100 +@@ -805,6 +805,24 @@ and is between 256 and 4096 characters. + gpt [EFI] Forces disk with valid GPT signature but + invalid Protective MBR to be treated as GPT. + ++ guestdev= [PCI,ACPI,XEN] ++ Format: {|}][,{|}[,...]] ++ Format of device path: [:]-.[-.[,...]][+iomul] ++ Format of sbdf: [:]:.[+iomul] ++ Specifies PCI device for guest domain. ++ If PCI-PCI bridge is specified, all PCI devices ++ behind PCI-PCI bridge are reserved. ++ +iomul means that this PCI function will share ++ IO ports with other +iomul functions under same ++ switch. NOTE: if +iomul is specfied, all the functions ++ of the device will share IO ports. ++ ++ guestiomuldev= [PCI,ACPI,XEN] ++ Format: [sbd][,][,...] ++ Format of sbdf: [:]: ++ Note: function shouldn't be specified. ++ Specifies PCI device for IO port multiplexing driver. ++ + gvp11= [HW,SCSI] + + hashdist= [KNL,NUMA] Large hashes allocated during boot +@@ -2133,6 +2151,10 @@ and is between 256 and 4096 characters. + Run specified binary instead of /init from the ramdisk, + used for early userspace startup. See initrd. + ++ reassign_resources [PCI,ACPI,XEN] ++ Use guestdev= parameter to reassign device's ++ resources, or specify =all here. ++ + reboot= [BUGS=X86-32,BUGS=ARM,BUGS=IA-64] Rebooting mode + Format: [,[,...]] + See arch/*/kernel/reboot.c or arch/*/kernel/process.c +--- sle11sp1-2010-03-22.orig/drivers/acpi/pci_root.c 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/acpi/pci_root.c 2010-03-11 09:11:37.000000000 +0100 +@@ -465,6 +465,40 @@ out: + } + EXPORT_SYMBOL(acpi_pci_osc_control_set); + ++#ifdef CONFIG_PCI_GUESTDEV ++#include ++ ++static ssize_t seg_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct list_head *entry; ++ ++ list_for_each(entry, &acpi_pci_roots) { ++ struct acpi_pci_root *root; ++ root = list_entry(entry, struct acpi_pci_root, node); ++ if (&root->device->dev == dev) ++ return sprintf(buf, "%04x\n", root->segment); ++ } ++ return 0; ++} ++static DEVICE_ATTR(seg, 0444, seg_show, NULL); ++ ++static ssize_t bbn_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct list_head *entry; ++ ++ list_for_each(entry, &acpi_pci_roots) { ++ struct acpi_pci_root *root; ++ root = list_entry(entry, struct acpi_pci_root, node); ++ if (&root->device->dev == dev) ++ return sprintf(buf, "%02x\n", root->bus_nr); ++ } ++ return 0; ++} ++static DEVICE_ATTR(bbn, 0444, bbn_show, NULL); ++#endif ++ + static int __devinit acpi_pci_root_add(struct acpi_device *device) + { + unsigned long long segment, bus; +@@ -576,6 +610,13 @@ static int __devinit acpi_pci_root_add(s + if (flags != base_flags) + acpi_pci_osc_support(root, flags); + ++#ifdef CONFIG_PCI_GUESTDEV ++ if (device_create_file(&device->dev, &dev_attr_seg)) ++ dev_warn(&device->dev, "could not create seg attr\n"); ++ if (device_create_file(&device->dev, &dev_attr_bbn)) ++ dev_warn(&device->dev, "could not create bbn attr\n"); ++#endif ++ + return 0; + + end: +@@ -614,3 +655,31 @@ static int __init acpi_pci_root_init(voi + } + + subsys_initcall(acpi_pci_root_init); ++ ++#ifdef CONFIG_PCI_GUESTDEV ++int acpi_pci_get_root_seg_bbn(char *hid, char *uid, int *seg, int *bbn) ++{ ++ struct list_head *entry; ++ ++ list_for_each(entry, &acpi_pci_roots) { ++ struct acpi_pci_root *root; ++ ++ root = list_entry(entry, struct acpi_pci_root, node); ++ if (strcmp(acpi_device_hid(root->device), hid)) ++ continue; ++ ++ if (!root->device->pnp.unique_id) { ++ if (strlen(uid)) ++ continue; ++ } else { ++ if (strcmp(root->device->pnp.unique_id, uid)) ++ continue; ++ } ++ ++ *seg = (int)root->segment; ++ *bbn = (int)root->bus_nr; ++ return TRUE; ++ } ++ return FALSE; ++} ++#endif +--- sle11sp1-2010-03-22.orig/drivers/acpi/scan.c 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/acpi/scan.c 2009-12-04 10:27:46.000000000 +0100 +@@ -168,6 +168,16 @@ acpi_device_hid_show(struct device *dev, + } + static DEVICE_ATTR(hid, 0444, acpi_device_hid_show, NULL); + ++#ifdef CONFIG_PCI_GUESTDEV ++static ssize_t ++acpi_device_uid_show(struct device *dev, struct device_attribute *attr, char *buf) { ++ struct acpi_device *acpi_dev = to_acpi_device(dev); ++ ++ return sprintf(buf, "%s\n", acpi_dev->pnp.unique_id); ++} ++static DEVICE_ATTR(uid, 0444, acpi_device_uid_show, NULL); ++#endif ++ + static ssize_t + acpi_device_path_show(struct device *dev, struct device_attribute *attr, char *buf) { + struct acpi_device *acpi_dev = to_acpi_device(dev); +@@ -208,6 +218,13 @@ static int acpi_device_setup_files(struc + if (result) + goto end; + ++#ifdef CONFIG_PCI_GUESTDEV ++ if(dev->pnp.unique_id) { ++ result = device_create_file(&dev->dev, &dev_attr_uid); ++ if(result) ++ goto end; ++ } ++#endif + /* + * If device has _EJ0, 'eject' file is created that is used to trigger + * hot-removal function from userland. +@@ -271,6 +288,9 @@ static void acpi_free_ids(struct acpi_de + kfree(id->id); + kfree(id); + } ++#ifdef CONFIG_PCI_GUESTDEV ++ kfree(device->pnp.unique_id); ++#endif + } + + static void acpi_device_release(struct device *dev) +@@ -1047,6 +1067,11 @@ static void acpi_device_set_id(struct ac + for (i = 0; i < cid_list->count; i++) + acpi_add_id(device, cid_list->ids[i].string); + } ++#ifdef CONFIG_PCI_GUESTDEV ++ if (info->valid & ACPI_VALID_UID) ++ device->pnp.unique_id = kstrdup(info->unique_id.string, ++ GFP_KERNEL); ++#endif + if (info->valid & ACPI_VALID_ADR) { + device->pnp.bus_address = info->address; + device->flags.bus_address = 1; +--- sle11sp1-2010-03-22.orig/drivers/pci/Kconfig 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/pci/Kconfig 2009-12-04 10:27:46.000000000 +0100 +@@ -42,6 +42,20 @@ config PCI_DEBUG + + When in doubt, say N. + ++config PCI_GUESTDEV ++ bool "PCI Device Reservation for Passthrough" ++ depends on PCI && ACPI && XEN ++ default y ++ help ++ Say Y here if you want to reserve PCI device for passthrough. ++ ++config PCI_IOMULTI ++ bool "PCI Device IO Multiplex for Passthrough" ++ depends on PCI && ACPI && XEN ++ default y ++ help ++ Say Y here if you need io multiplexing. ++ + config PCI_STUB + tristate "PCI Stub driver" + depends on PCI +--- sle11sp1-2010-03-22.orig/drivers/pci/Makefile 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/pci/Makefile 2009-12-04 10:27:46.000000000 +0100 +@@ -7,6 +7,8 @@ obj-y += access.o bus.o probe.o remove. + irq.o + obj-$(CONFIG_PROC_FS) += proc.o + obj-$(CONFIG_SYSFS) += slot.o ++obj-$(CONFIG_PCI_GUESTDEV) += guestdev.o ++obj-$(CONFIG_PCI_IOMULTI) += iomulti.o + + obj-$(CONFIG_PCI_LEGACY) += legacy.o + CFLAGS_legacy.o += -Wno-deprecated-declarations +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/drivers/pci/guestdev.c 2010-01-29 16:29:49.000000000 +0100 +@@ -0,0 +1,892 @@ ++/* ++ * Copyright (c) 2008, 2009 NEC Corporation. ++ * Copyright (c) 2009 Isaku Yamahata ++ * VA Linux Systems Japan K.K. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms and conditions of the GNU General Public License, ++ * version 2, as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ * more details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple ++ * Place - Suite 330, Boston, MA 02111-1307 USA. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define HID_LEN 8 ++#define UID_LEN 8 ++#define DEV_LEN 2 ++#define FUNC_LEN 1 ++#define DEV_NUM_MAX 31 ++#define FUNC_NUM_MAX 7 ++#define INVALID_SEG (-1) ++#define INVALID_BBN (-1) ++#define GUESTDEV_STR_MAX 128 ++ ++#define GUESTDEV_FLAG_TYPE_MASK 0x3 ++#define GUESTDEV_FLAG_DEVICEPATH 0x1 ++#define GUESTDEV_FLAG_SBDF 0x2 ++ ++#define GUESTDEV_OPT_IOMUL 0x1 ++ ++struct guestdev { ++ int flags; ++ int options; ++ struct list_head root_list; ++ union { ++ struct devicepath { ++ char hid[HID_LEN + 1]; ++ char uid[UID_LEN + 1]; ++ int seg; ++ int bbn; ++ struct devicepath_node *child; ++ } devicepath; ++ struct sbdf { ++ int seg; ++ int bus; ++ int dev; ++ int func; ++ } sbdf; ++ } u; ++}; ++ ++struct devicepath_node { ++ int dev; ++ int func; ++ struct devicepath_node *child; ++}; ++ ++struct pcidev_sbdf { ++ int seg; ++ int bus; ++ struct pcidev_sbdf_node *child; ++}; ++ ++struct pcidev_sbdf_node { ++ int dev; ++ int func; ++ struct pcidev_sbdf_node *child; ++}; ++ ++static char guestdev_param[COMMAND_LINE_SIZE]; ++static LIST_HEAD(guestdev_list); ++ ++/* Get hid and uid */ ++static int __init pci_get_hid_uid(char *str, char *hid, char *uid) ++{ ++ char *sp, *ep; ++ int len; ++ ++ sp = str; ++ ep = strchr(sp, ':'); ++ if (!ep) { ++ ep = strchr(sp, '-'); ++ if (!ep) ++ goto format_err_end; ++ } ++ /* hid length */ ++ len = ep - sp; ++ if (len <= 0 || HID_LEN < len) ++ goto format_err_end; ++ ++ strlcpy(hid, sp, len); ++ ++ if (*ep == '-') { /* no uid */ ++ uid[0] = '\0'; ++ return TRUE; ++ } ++ ++ sp = ep + 1; ++ ep = strchr(sp, '-'); ++ if (!ep) ++ ep = strchr(sp, '\0'); ++ ++ /* uid length */ ++ len = ep - sp; ++ if (len <= 0 || UID_LEN < len) ++ goto format_err_end; ++ ++ strlcpy(uid, sp, len); ++ return TRUE; ++ ++format_err_end: ++ return FALSE; ++} ++ ++/* Get device and function */ ++static int __init pci_get_dev_func(char *str, int *dev, int *func) ++{ ++ if (sscanf(str, "%02x.%01x", dev, func) != 2) ++ goto format_err_end; ++ ++ if (*dev < 0 || DEV_NUM_MAX < *dev) ++ goto format_err_end; ++ ++ if (*func < 0 || FUNC_NUM_MAX < *func) ++ goto format_err_end; ++ ++ return TRUE; ++ ++format_err_end: ++ return FALSE; ++} ++ ++/* Check extended guestdev parameter format error */ ++static int __init pci_check_extended_guestdev_format(char *str) ++{ ++ int flg; ++ char *p; ++ ++ /* Check extended format */ ++ if (strpbrk(str, "(|)") == NULL) ++ return TRUE; ++ ++ flg = 0; ++ p = str; ++ while (*p) { ++ switch (*p) { ++ case '(': ++ /* Check nesting error */ ++ if (flg != 0) ++ goto format_err_end; ++ flg = 1; ++ /* Check position of '(' is head or ++ previos charactor of '(' is not '-'. */ ++ if (p == str || *(p - 1) != '-') ++ goto format_err_end; ++ break; ++ case ')': ++ /* Check nesting error */ ++ if (flg != 1) ++ goto format_err_end; ++ flg = 0; ++ /* Check next charactor of ')' is not '\0' */ ++ if (*(p + 1) != '\0') ++ goto format_err_end; ++ break; ++ case '|': ++ /* Check position of '|' is outside of '(' and ')' */ ++ if (flg != 1) ++ goto format_err_end; ++ break; ++ default: ++ break; ++ } ++ p++; ++ } ++ /* Check number of '(' and ')' are not equal */ ++ if (flg != 0) ++ goto format_err_end; ++ return TRUE; ++ ++format_err_end: ++ printk(KERN_ERR ++ "PCI: The format of the guestdev parameter is illegal. [%s]\n", ++ str); ++ return FALSE; ++} ++ ++/* Make guestdev strings */ ++static void pci_make_guestdev_str(struct guestdev *gdev, ++ char *gdev_str, int buf_size) ++{ ++ struct devicepath_node *node; ++ int count; ++ ++ switch (gdev->flags & GUESTDEV_FLAG_TYPE_MASK) { ++ case GUESTDEV_FLAG_DEVICEPATH: ++ memset(gdev_str, 0, buf_size); ++ ++ if (strlen(gdev->u.devicepath.uid)) ++ count = snprintf(gdev_str, buf_size, "%s:%s", ++ gdev->u.devicepath.hid, ++ gdev->u.devicepath.uid); ++ else ++ count = snprintf(gdev_str, buf_size, "%s", ++ gdev->u.devicepath.hid); ++ if (count < 0) ++ return; ++ ++ node = gdev->u.devicepath.child; ++ while (node) { ++ gdev_str += count; ++ buf_size -= count; ++ if (buf_size <= 0) ++ return; ++ count = snprintf(gdev_str, buf_size, "-%02x.%01x", ++ node->dev, node->func); ++ if (count < 0) ++ return; ++ node = node->child; ++ } ++ break; ++ case GUESTDEV_FLAG_SBDF: ++ snprintf(gdev_str, buf_size, "%04x:%02x:%02x.%01x", ++ gdev->u.sbdf.seg, gdev->u.sbdf.bus, ++ gdev->u.sbdf.dev, gdev->u.sbdf.func); ++ break; ++ default: ++ BUG(); ++ } ++} ++ ++/* Free guestdev and nodes */ ++static void __init pci_free_guestdev(struct guestdev *gdev) ++{ ++ struct devicepath_node *node, *next; ++ ++ if (!gdev) ++ return; ++ if (gdev->flags & GUESTDEV_FLAG_DEVICEPATH) { ++ node = gdev->u.devicepath.child; ++ while (node) { ++ next = node->child; ++ kfree(node); ++ node = next; ++ } ++ } ++ list_del(&gdev->root_list); ++ kfree(gdev); ++} ++ ++/* Copy guestdev and nodes */ ++struct guestdev __init *pci_copy_guestdev(struct guestdev *gdev_src) ++{ ++ struct guestdev *gdev; ++ struct devicepath_node *node, *node_src, *node_upper; ++ ++ BUG_ON(!(gdev_src->flags & GUESTDEV_FLAG_DEVICEPATH)); ++ ++ gdev = kmalloc(sizeof(*gdev), GFP_KERNEL); ++ if (!gdev) ++ goto allocate_err_end; ++ ++ memset(gdev, 0, sizeof(*gdev)); ++ INIT_LIST_HEAD(&gdev->root_list); ++ gdev->flags = gdev_src->flags; ++ gdev->options = gdev_src->options; ++ strcpy(gdev->u.devicepath.hid, gdev_src->u.devicepath.hid); ++ strcpy(gdev->u.devicepath.uid, gdev_src->u.devicepath.uid); ++ gdev->u.devicepath.seg = gdev_src->u.devicepath.seg; ++ gdev->u.devicepath.bbn = gdev_src->u.devicepath.bbn; ++ ++ node_upper = NULL; ++ ++ node_src = gdev_src->u.devicepath.child; ++ while (node_src) { ++ node = kmalloc(sizeof(*node), GFP_KERNEL); ++ if (!node) ++ goto allocate_err_end; ++ memset(node, 0, sizeof(*node)); ++ node->dev = node_src->dev; ++ node->func = node_src->func; ++ if (!node_upper) ++ gdev->u.devicepath.child = node; ++ else ++ node_upper->child = node; ++ node_upper = node; ++ node_src = node_src->child; ++ } ++ ++ return gdev; ++ ++allocate_err_end: ++ if (gdev) ++ pci_free_guestdev(gdev); ++ printk(KERN_ERR "PCI: Failed to allocate memory.\n"); ++ return NULL; ++} ++ ++/* Make guestdev from path strings */ ++static int __init pci_make_devicepath_guestdev(char *path_str, int options) ++{ ++ char hid[HID_LEN + 1], uid[UID_LEN + 1]; ++ char *sp, *ep; ++ struct guestdev *gdev, *gdev_org; ++ struct devicepath_node *node, *node_tmp; ++ int dev, func, ret_val; ++ ++ ret_val = 0; ++ gdev = gdev_org = NULL; ++ sp = path_str; ++ /* Look for end of hid:uid'-' */ ++ ep = strchr(sp, '-'); ++ /* Only hid, uid. (No dev, func) */ ++ if (!ep) ++ goto format_err_end; ++ ++ memset(hid, 0 ,sizeof(hid)); ++ memset(uid, 0, sizeof(uid)); ++ if (!pci_get_hid_uid(sp, hid, uid)) ++ goto format_err_end; ++ ++ gdev_org = kmalloc(sizeof(*gdev_org), GFP_KERNEL); ++ if (!gdev_org) ++ goto allocate_err_end; ++ memset(gdev_org, 0, sizeof(*gdev_org)); ++ INIT_LIST_HEAD(&gdev_org->root_list); ++ gdev_org->flags = GUESTDEV_FLAG_DEVICEPATH; ++ gdev_org->options = options; ++ strcpy(gdev_org->u.devicepath.hid, hid); ++ strcpy(gdev_org->u.devicepath.uid, uid); ++ gdev_org->u.devicepath.seg = INVALID_SEG; ++ gdev_org->u.devicepath.bbn = INVALID_BBN; ++ ++ gdev = gdev_org; ++ ++ sp = ep + 1; ++ ep = sp; ++ do { ++ if (*sp == '(') { ++ sp++; ++ if (strchr(sp, '|')) { ++ gdev = pci_copy_guestdev(gdev_org); ++ if (!gdev) { ++ ret_val = -ENOMEM; ++ goto end; ++ } ++ } ++ continue; ++ } ++ if (gdev && pci_get_dev_func(sp, &dev, &func)) { ++ node = kmalloc(sizeof(*node), GFP_KERNEL); ++ if (!node) ++ goto allocate_err_end; ++ memset(node, 0, sizeof(*node)); ++ node->dev = dev; ++ node->func = func; ++ /* add node to end of guestdev */ ++ if (gdev->u.devicepath.child) { ++ node_tmp = gdev->u.devicepath.child; ++ while (node_tmp->child) { ++ node_tmp = node_tmp->child; ++ } ++ node_tmp->child = node; ++ } else ++ gdev->u.devicepath.child = node; ++ } else if (gdev) { ++ printk(KERN_ERR ++ "PCI: Can't obtain dev# and #func# from %s.\n", ++ sp); ++ ret_val = -EINVAL; ++ if (gdev == gdev_org) ++ goto end; ++ pci_free_guestdev(gdev); ++ gdev = NULL; ++ } ++ ++ ep = strpbrk(sp, "-|)"); ++ if (!ep) ++ ep = strchr(sp, '\0'); ++ /* Is *ep '|' OR ')' OR '\0' ? */ ++ if (*ep != '-') { ++ if (gdev) ++ list_add_tail(&gdev->root_list, &guestdev_list); ++ if (*ep == '|') { ++ /* Between '|' and '|' ? */ ++ if (strchr(ep + 1, '|')) { ++ gdev = pci_copy_guestdev(gdev_org); ++ if (!gdev) { ++ ret_val = -ENOMEM; ++ goto end; ++ } ++ } else { ++ gdev = gdev_org; ++ gdev_org = NULL; ++ } ++ } else { ++ gdev_org = NULL; ++ gdev = NULL; ++ } ++ } ++ if (*ep == ')') ++ ep++; ++ sp = ep + 1; ++ } while (*ep != '\0'); ++ ++ goto end; ++ ++format_err_end: ++ printk(KERN_ERR ++ "PCI: The format of the guestdev parameter is illegal. [%s]\n", ++ path_str); ++ ret_val = -EINVAL; ++ goto end; ++ ++allocate_err_end: ++ printk(KERN_ERR "PCI: Failed to allocate memory.\n"); ++ ret_val = -ENOMEM; ++ goto end; ++ ++end: ++ if (gdev_org && (gdev_org != gdev)) ++ pci_free_guestdev(gdev_org); ++ if (gdev) ++ pci_free_guestdev(gdev); ++ return ret_val; ++} ++ ++static int __init pci_make_sbdf_guestdev(char* str, int options) ++{ ++ struct guestdev *gdev; ++ int seg, bus, dev, func; ++ ++ if (sscanf(str, "%x:%x:%x.%x", &seg, &bus, &dev, &func) != 4) { ++ seg = 0; ++ if (sscanf(str, "%x:%x.%x", &bus, &dev, &func) != 3) ++ return -EINVAL; ++ } ++ gdev = kmalloc(sizeof(*gdev), GFP_KERNEL); ++ if (!gdev) { ++ printk(KERN_ERR "PCI: Failed to allocate memory.\n"); ++ return -ENOMEM; ++ } ++ INIT_LIST_HEAD(&gdev->root_list); ++ gdev->flags = GUESTDEV_FLAG_SBDF; ++ gdev->options = options; ++ gdev->u.sbdf.seg = seg; ++ gdev->u.sbdf.bus = bus; ++ gdev->u.sbdf.dev = dev; ++ gdev->u.sbdf.func = func; ++ list_add_tail(&gdev->root_list, &guestdev_list); ++ return 0; ++} ++ ++static int __init pci_parse_options(const char *str) ++{ ++ int options = 0; ++ char *ep; ++ ++ while (str) { ++ str++; ++ ep = strchr(str, '+'); ++ if (ep) ++ ep = '\0'; /* Chop */ ++ ++ if (!strcmp(str, "iomul")) ++ options |= GUESTDEV_OPT_IOMUL; ++ ++ str = ep; ++ } ++ return options; ++} ++ ++/* Parse guestdev parameter */ ++static int __init pci_parse_guestdev(void) ++{ ++ int len; ++ char *sp, *ep, *op; ++ int options; ++ struct list_head *head; ++ struct guestdev *gdev; ++ char path_str[GUESTDEV_STR_MAX]; ++ int ret_val = 0; ++ ++ len = strlen(guestdev_param); ++ if (len == 0) ++ return 0; ++ ++ sp = guestdev_param; ++ ++ do { ++ ep = strchr(sp, ','); ++ /* Chop */ ++ if (ep) ++ *ep = '\0'; ++ options = 0; ++ op = strchr(sp, '+'); ++ if (op && (!ep || op < ep)) { ++ options = pci_parse_options(op); ++ *op = '\0'; /* Chop */ ++ } ++ ret_val = pci_make_sbdf_guestdev(sp, options); ++ if (ret_val == -EINVAL) { ++ if (pci_check_extended_guestdev_format(sp)) { ++ ret_val = pci_make_devicepath_guestdev( ++ sp, options); ++ if (ret_val && ret_val != -EINVAL) ++ break; ++ } ++ } else if (ret_val) ++ break; ++ ++ if (ep) ++ ep++; ++ sp = ep; ++ } while (ep); ++ ++ list_for_each(head, &guestdev_list) { ++ gdev = list_entry(head, struct guestdev, root_list); ++ pci_make_guestdev_str(gdev, path_str, GUESTDEV_STR_MAX); ++ printk(KERN_DEBUG ++ "PCI: %s has been reserved for guest domain.\n", ++ path_str); ++ } ++ return 0; ++} ++ ++arch_initcall(pci_parse_guestdev); ++ ++/* Get command line */ ++static int __init pci_guestdev_setup(char *str) ++{ ++ if (strlen(str) >= COMMAND_LINE_SIZE) ++ return 0; ++ strlcpy(guestdev_param, str, sizeof(guestdev_param)); ++ return 1; ++} ++ ++__setup("guestdev=", pci_guestdev_setup); ++ ++/* Free sbdf and nodes */ ++static void pci_free_sbdf(struct pcidev_sbdf *sbdf) ++{ ++ struct pcidev_sbdf_node *node, *next; ++ ++ node = sbdf->child; ++ while (node) { ++ next = node->child; ++ kfree(node); ++ node = next; ++ } ++ /* Skip kfree(sbdf) */ ++} ++ ++/* Does PCI device belong to sub tree specified by guestdev with device path? */ ++typedef int (*pci_node_match_t)(const struct devicepath_node *gdev_node, ++ const struct pcidev_sbdf_node *sbdf_node, ++ int options); ++ ++static int pci_node_match(const struct devicepath_node *gdev_node, ++ const struct pcidev_sbdf_node *sbdf_node, ++ int options_unused) ++{ ++ return (gdev_node->dev == sbdf_node->dev && ++ gdev_node->func == sbdf_node->func); ++} ++ ++static int pci_is_in_devicepath_sub_tree(struct guestdev *gdev, ++ struct pcidev_sbdf *sbdf, ++ pci_node_match_t match) ++{ ++ int seg, bbn; ++ struct devicepath_node *gdev_node; ++ struct pcidev_sbdf_node *sbdf_node; ++ ++ if (!gdev || !sbdf) ++ return FALSE; ++ ++ BUG_ON(!(gdev->flags & GUESTDEV_FLAG_DEVICEPATH)); ++ ++ /* Compare seg and bbn */ ++ if (gdev->u.devicepath.seg == INVALID_SEG || ++ gdev->u.devicepath.bbn == INVALID_BBN) { ++ if (acpi_pci_get_root_seg_bbn(gdev->u.devicepath.hid, ++ gdev->u.devicepath.uid, &seg, &bbn)) { ++ gdev->u.devicepath.seg = seg; ++ gdev->u.devicepath.bbn = bbn; ++ } else ++ return FALSE; ++ } ++ ++ if (gdev->u.devicepath.seg != sbdf->seg || ++ gdev->u.devicepath.bbn != sbdf->bus) ++ return FALSE; ++ ++ gdev_node = gdev->u.devicepath.child; ++ sbdf_node = sbdf->child; ++ ++ /* Compare dev and func */ ++ while (gdev_node) { ++ if (!sbdf_node) ++ return FALSE; ++ if (!match(gdev_node, sbdf_node, gdev->options)) ++ return FALSE; ++ gdev_node = gdev_node->child; ++ sbdf_node = sbdf_node->child; ++ } ++ return TRUE; ++} ++ ++/* Get sbdf from device */ ++static int pci_get_sbdf_from_pcidev( ++ struct pci_dev *dev, struct pcidev_sbdf *sbdf) ++{ ++ struct pcidev_sbdf_node *node; ++ ++ if (!dev) ++ return FALSE; ++ ++ for(;;) { ++ node = kmalloc(sizeof(*node), GFP_KERNEL); ++ if (!node) { ++ printk(KERN_ERR "PCI: Failed to allocate memory.\n"); ++ goto err_end; ++ } ++ memset(node, 0, sizeof(*node)); ++ node->dev = PCI_SLOT(dev->devfn); ++ node->func = PCI_FUNC(dev->devfn); ++ ++ if (!sbdf->child) ++ sbdf->child = node; ++ else { ++ node->child = sbdf->child; ++ sbdf->child = node; ++ } ++ if (!dev->bus) ++ goto err_end; ++ if (!dev->bus->self) ++ break; ++ dev = dev->bus->self; ++ } ++ if (sscanf(dev_name(&dev->dev), "%04x:%02x", &sbdf->seg, &sbdf->bus) != 2) ++ goto err_end; ++ return TRUE; ++ ++err_end: ++ pci_free_sbdf(sbdf); ++ return FALSE; ++} ++ ++/* Does PCI device belong to sub tree specified by guestdev with sbdf? */ ++typedef int (*pci_sbdf_match_t)(const struct guestdev *gdev, ++ const struct pci_dev *dev); ++ ++static int pci_sbdf_match(const struct guestdev *gdev, ++ const struct pci_dev *dev) ++{ ++ int seg, bus; ++ ++ if (sscanf(dev_name(&dev->dev), "%04x:%02x", &seg, &bus) != 2) ++ return FALSE; ++ ++ return gdev->u.sbdf.seg == seg && ++ gdev->u.sbdf.bus == bus && ++ gdev->u.sbdf.dev == PCI_SLOT(dev->devfn) && ++ gdev->u.sbdf.func == PCI_FUNC(dev->devfn); ++} ++ ++static int pci_is_in_sbdf_sub_tree(struct guestdev *gdev, struct pci_dev *dev, ++ pci_sbdf_match_t match) ++{ ++ BUG_ON(!(gdev->flags & GUESTDEV_FLAG_SBDF)); ++ for (;;) { ++ if (match(gdev, dev)) ++ return TRUE; ++ if (!dev->bus || !dev->bus->self) ++ break; ++ dev = dev->bus->self; ++ } ++ return FALSE; ++} ++ ++/* Does PCI device belong to sub tree specified by guestdev parameter? */ ++static int __pci_is_guestdev(struct pci_dev *dev, pci_node_match_t node_match, ++ pci_sbdf_match_t sbdf_match) ++{ ++ struct guestdev *gdev; ++ struct pcidev_sbdf pcidev_sbdf, *sbdf = NULL; ++ struct list_head *head; ++ int result = FALSE; ++ ++ if (!dev) ++ return FALSE; ++ ++ list_for_each(head, &guestdev_list) { ++ gdev = list_entry(head, struct guestdev, root_list); ++ switch (gdev->flags & GUESTDEV_FLAG_TYPE_MASK) { ++ case GUESTDEV_FLAG_DEVICEPATH: ++ if (sbdf == NULL) { ++ sbdf = &pcidev_sbdf; ++ memset(sbdf, 0 ,sizeof(*sbdf)); ++ if (!pci_get_sbdf_from_pcidev(dev, sbdf)) ++ goto out; ++ } ++ if (pci_is_in_devicepath_sub_tree(gdev, sbdf, ++ node_match)) { ++ result = TRUE; ++ goto out; ++ } ++ break; ++ case GUESTDEV_FLAG_SBDF: ++ if (pci_is_in_sbdf_sub_tree(gdev, dev, sbdf_match)) { ++ result = TRUE; ++ goto out; ++ } ++ break; ++ default: ++ BUG(); ++ } ++ } ++out: ++ if (sbdf) ++ pci_free_sbdf(sbdf); ++ return result; ++} ++ ++int pci_is_guestdev(struct pci_dev *dev) ++{ ++ return __pci_is_guestdev(dev, pci_node_match, pci_sbdf_match); ++} ++EXPORT_SYMBOL_GPL(pci_is_guestdev); ++ ++static int reassign_resources; ++ ++static int __init pci_set_reassign_resources(char *str) ++{ ++ if (str && !strcmp(str, "all")) ++ reassign_resources = -1; ++ else ++ reassign_resources = 1; ++ ++ return 1; ++} ++__setup("reassign_resources", pci_set_reassign_resources); ++ ++int pci_is_guestdev_to_reassign(struct pci_dev *dev) ++{ ++ if (reassign_resources < 0) ++ return TRUE; ++ if (reassign_resources) ++ return pci_is_guestdev(dev); ++ return FALSE; ++} ++ ++#ifdef CONFIG_PCI_IOMULTI ++static int pci_iomul_node_match(const struct devicepath_node *gdev_node, ++ const struct pcidev_sbdf_node *sbdf_node, ++ int options) ++{ ++ return (options & GUESTDEV_OPT_IOMUL) && ++ ((gdev_node->child != NULL && ++ sbdf_node->child != NULL && ++ gdev_node->dev == sbdf_node->dev && ++ gdev_node->func == sbdf_node->func) || ++ (gdev_node->child == NULL && ++ sbdf_node->child == NULL && ++ gdev_node->dev == sbdf_node->dev)); ++} ++ ++static int pci_iomul_sbdf_match(const struct guestdev *gdev, ++ const struct pci_dev *dev) ++{ ++ int seg, bus; ++ ++ if (sscanf(dev_name(&dev->dev), "%04x:%02x", &seg, &bus) != 2) ++ return FALSE; ++ ++ return (gdev->options & GUESTDEV_OPT_IOMUL) && ++ gdev->u.sbdf.seg == seg && ++ gdev->u.sbdf.bus == bus && ++ gdev->u.sbdf.dev == PCI_SLOT(dev->devfn); ++} ++ ++int pci_is_iomuldev(struct pci_dev *dev) ++{ ++ return __pci_is_guestdev(dev, ++ pci_iomul_node_match, pci_iomul_sbdf_match); ++} ++#endif /* CONFIG_PCI_IOMULTI */ ++ ++/* Check whether the devicepath exists under the pci root bus */ ++static int __init pci_check_devicepath_exists( ++ struct guestdev *gdev, struct pci_bus *bus) ++{ ++ struct devicepath_node *node; ++ struct pci_dev *dev; ++ ++ BUG_ON(!(gdev->flags & GUESTDEV_FLAG_DEVICEPATH)); ++ ++ node = gdev->u.devicepath.child; ++ while (node) { ++ if (!bus) ++ return FALSE; ++ dev = pci_get_slot(bus, PCI_DEVFN(node->dev, node->func)); ++ if (!dev) ++ return FALSE; ++ bus = dev->subordinate; ++ node = node->child; ++ pci_dev_put(dev); ++ } ++ return TRUE; ++} ++ ++/* Check whether the guestdev exists in the PCI device tree */ ++static int __init pci_check_guestdev_exists(void) ++{ ++ struct list_head *head; ++ struct guestdev *gdev; ++ int seg, bbn; ++ struct pci_bus *bus; ++ struct pci_dev *dev; ++ char path_str[GUESTDEV_STR_MAX]; ++ ++ list_for_each(head, &guestdev_list) { ++ gdev = list_entry(head, struct guestdev, root_list); ++ switch (gdev->flags & GUESTDEV_FLAG_TYPE_MASK) { ++ case GUESTDEV_FLAG_DEVICEPATH: ++ if (gdev->u.devicepath.seg == INVALID_SEG || ++ gdev->u.devicepath.bbn == INVALID_BBN) { ++ if (acpi_pci_get_root_seg_bbn( ++ gdev->u.devicepath.hid, ++ gdev->u.devicepath.uid, &seg, &bbn)) { ++ gdev->u.devicepath.seg = seg; ++ gdev->u.devicepath.bbn = bbn; ++ } else { ++ pci_make_guestdev_str(gdev, ++ path_str, GUESTDEV_STR_MAX); ++ printk(KERN_INFO ++ "PCI: Device does not exist. %s\n", ++ path_str); ++ continue; ++ } ++ } ++ ++ bus = pci_find_bus(gdev->u.devicepath.seg, ++ gdev->u.devicepath.bbn); ++ if (!bus || ++ !pci_check_devicepath_exists(gdev, bus)) { ++ pci_make_guestdev_str(gdev, path_str, ++ GUESTDEV_STR_MAX); ++ printk(KERN_INFO ++ "PCI: Device does not exist. %s\n", ++ path_str); ++ } ++ break; ++ case GUESTDEV_FLAG_SBDF: ++ bus = pci_find_bus(gdev->u.sbdf.seg, gdev->u.sbdf.bus); ++ if (bus) { ++ dev = pci_get_slot(bus, ++ PCI_DEVFN(gdev->u.sbdf.dev, ++ gdev->u.sbdf.func)); ++ if (dev) { ++ pci_dev_put(dev); ++ continue; ++ } ++ } ++ pci_make_guestdev_str(gdev, path_str, GUESTDEV_STR_MAX); ++ printk(KERN_INFO "PCI: Device does not exist. %s\n", ++ path_str); ++ break; ++ default: ++ BUG(); ++ } ++ } ++ return 0; ++} ++ ++fs_initcall(pci_check_guestdev_exists); ++ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/drivers/pci/iomulti.c 2009-12-04 10:27:46.000000000 +0100 +@@ -0,0 +1,1415 @@ ++/* ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ++ * ++ * Copyright (c) 2009 Isaku Yamahata ++ * VA Linux Systems Japan K.K. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "pci.h" ++#include "iomulti.h" ++ ++#define PCI_NUM_BARS 6 ++#define PCI_BUS_MAX 255 ++#define PCI_DEV_MAX 31 ++#define PCI_FUNC_MAX 7 ++#define PCI_NUM_FUNC 8 ++ ++/* see pci_resource_len */ ++static inline resource_size_t pci_iomul_len(const struct resource* r) ++{ ++ if (r->start == 0 && r->start == r->end) ++ return 0; ++ return r->end - r->start + 1; ++} ++ ++#define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1)) ++/* stolen from pbus_size_io() */ ++static unsigned long pdev_size_io(struct pci_dev *pdev) ++{ ++ unsigned long size = 0, size1 = 0; ++ int i; ++ ++ for (i = 0; i < PCI_NUM_RESOURCES; i++) { ++ struct resource *r = &pdev->resource[i]; ++ unsigned long r_size; ++ ++ if (!(r->flags & IORESOURCE_IO)) ++ continue; ++ ++ r_size = r->end - r->start + 1; ++ ++ if (r_size < 0x400) ++ /* Might be re-aligned for ISA */ ++ size += r_size; ++ else ++ size1 += r_size; ++ } ++ ++/* To be fixed in 2.5: we should have sort of HAVE_ISA ++ flag in the struct pci_bus. */ ++#if defined(CONFIG_ISA) || defined(CONFIG_EISA) ++ size = (size & 0xff) + ((size & ~0xffUL) << 2); ++#endif ++ size = ROUND_UP(size + size1, 4096); ++ return size; ++} ++ ++/* ++ * primary bus number of PCI-PCI bridge in switch on which ++ * this slots sits. ++ * i.e. the primary bus number of PCI-PCI bridge of downstream port ++ * or root port in switch. ++ * the secondary bus number of PCI-PCI bridge of upstream port ++ * in switch. ++ */ ++static inline unsigned char pci_dev_switch_busnr(struct pci_dev *pdev) ++{ ++ if (pci_find_capability(pdev, PCI_CAP_ID_EXP)) ++ return pdev->bus->primary; ++ return pdev->bus->number; ++} ++ ++struct pci_iomul_func { ++ int segment; ++ uint8_t bus; ++ uint8_t devfn; ++ ++ /* only start and end are used */ ++ unsigned long io_size; ++ uint8_t io_bar; ++ struct resource resource[PCI_NUM_BARS]; ++ struct resource dummy_parent; ++}; ++ ++struct pci_iomul_switch { ++ struct list_head list; /* bus_list_lock protects */ ++ ++ /* ++ * This lock the following entry and following ++ * pci_iomul_slot/pci_iomul_func. ++ */ ++ struct mutex lock; ++ struct kref kref; ++ ++ struct resource io_resource; ++ struct resource *io_region; ++ unsigned int count; ++ struct pci_dev *current_pdev; ++ ++ int segment; ++ uint8_t bus; ++ ++ uint32_t io_base; ++ uint32_t io_limit; ++ ++ /* func which has the largeset io size*/ ++ struct pci_iomul_func *func; ++ ++ struct list_head slots; ++}; ++ ++struct pci_iomul_slot { ++ struct list_head sibling; ++ struct kref kref; ++ /* ++ * busnr ++ * when pcie, the primary busnr of the PCI-PCI bridge on which ++ * this devices sits. ++ */ ++ uint8_t switch_busnr; ++ struct resource dummy_parent[PCI_NUM_RESOURCES - PCI_BRIDGE_RESOURCES]; ++ ++ /* device */ ++ int segment; ++ uint8_t bus; ++ uint8_t dev; ++ ++ struct pci_iomul_func *func[PCI_NUM_FUNC]; ++}; ++ ++static LIST_HEAD(switch_list); ++static DEFINE_MUTEX(switch_list_lock); ++ ++/*****************************************************************************/ ++static int inline pci_iomul_switch_io_allocated( ++ const struct pci_iomul_switch *sw) ++{ ++ return !(sw->io_base == 0 || sw->io_base > sw->io_limit); ++} ++ ++static struct pci_iomul_switch *pci_iomul_find_switch_locked(int segment, ++ uint8_t bus) ++{ ++ struct pci_iomul_switch *sw; ++ ++ BUG_ON(!mutex_is_locked(&switch_list_lock)); ++ list_for_each_entry(sw, &switch_list, list) { ++ if (sw->segment == segment && sw->bus == bus) ++ return sw; ++ } ++ return NULL; ++} ++ ++static struct pci_iomul_slot *pci_iomul_find_slot_locked( ++ struct pci_iomul_switch *sw, uint8_t busnr, uint8_t dev) ++{ ++ struct pci_iomul_slot *slot; ++ ++ BUG_ON(!mutex_is_locked(&sw->lock)); ++ list_for_each_entry(slot, &sw->slots, sibling) { ++ if (slot->bus == busnr && slot->dev == dev) ++ return slot; ++ } ++ return NULL; ++} ++ ++static void pci_iomul_switch_get(struct pci_iomul_switch *sw); ++/* on successfull exit, sw->lock is locked for use slot and ++ * refrence count of sw is incremented. ++ */ ++static void pci_iomul_get_lock_switch(struct pci_dev *pdev, ++ struct pci_iomul_switch **swp, ++ struct pci_iomul_slot **slot) ++{ ++ mutex_lock(&switch_list_lock); ++ ++ *swp = pci_iomul_find_switch_locked(pci_domain_nr(pdev->bus), ++ pci_dev_switch_busnr(pdev)); ++ if (*swp == NULL) { ++ *slot = NULL; ++ goto out; ++ } ++ ++ mutex_lock(&(*swp)->lock); ++ *slot = pci_iomul_find_slot_locked(*swp, pdev->bus->number, ++ PCI_SLOT(pdev->devfn)); ++ if (*slot == NULL) { ++ mutex_unlock(&(*swp)->lock); ++ *swp = NULL; ++ } else { ++ pci_iomul_switch_get(*swp); ++ } ++out: ++ mutex_unlock(&switch_list_lock); ++} ++ ++static struct pci_iomul_switch *pci_iomul_switch_alloc(int segment, ++ uint8_t bus) ++{ ++ struct pci_iomul_switch *sw; ++ ++ BUG_ON(!mutex_is_locked(&switch_list_lock)); ++ ++ sw = kmalloc(sizeof(*sw), GFP_KERNEL); ++ ++ mutex_init(&sw->lock); ++ kref_init(&sw->kref); ++ sw->io_region = NULL; ++ sw->count = 0; ++ sw->current_pdev = NULL; ++ sw->segment = segment; ++ sw->bus = bus; ++ sw->io_base = 0; ++ sw->io_limit = 0; ++ sw->func = NULL; ++ INIT_LIST_HEAD(&sw->slots); ++ ++ return sw; ++} ++ ++static void pci_iomul_switch_add_locked(struct pci_iomul_switch *sw) ++{ ++ BUG_ON(!mutex_is_locked(&switch_list_lock)); ++ list_add(&sw->list, &switch_list); ++} ++ ++#ifdef CONFIG_HOTPLUG_PCI ++static void pci_iomul_switch_del_locked(struct pci_iomul_switch *sw) ++{ ++ BUG_ON(!mutex_is_locked(&switch_list_lock)); ++ list_del(&sw->list); ++} ++#endif ++ ++static void pci_iomul_switch_get(struct pci_iomul_switch *sw) ++{ ++ kref_get(&sw->kref); ++} ++ ++static void pci_iomul_switch_release(struct kref *kref) ++{ ++ struct pci_iomul_switch *sw = container_of(kref, ++ struct pci_iomul_switch, ++ kref); ++ kfree(sw); ++} ++ ++static void pci_iomul_switch_put(struct pci_iomul_switch *sw) ++{ ++ kref_put(&sw->kref, &pci_iomul_switch_release); ++} ++ ++static int __devinit pci_iomul_slot_init(struct pci_dev *pdev, ++ struct pci_iomul_slot *slot) ++{ ++ u16 rpcap; ++ u16 cap; ++ ++ rpcap = pci_find_capability(pdev, PCI_CAP_ID_EXP); ++ if (!rpcap) { ++ /* pci device isn't supported */ ++ printk(KERN_INFO ++ "PCI: sharing io port of non PCIe device %s " ++ "isn't supported. ignoring.\n", ++ pci_name(pdev)); ++ return -ENOSYS; ++ } ++ ++ pci_read_config_word(pdev, rpcap + PCI_CAP_FLAGS, &cap); ++ switch ((cap & PCI_EXP_FLAGS_TYPE) >> 4) { ++ case PCI_EXP_TYPE_RC_END: ++ printk(KERN_INFO ++ "PCI: io port sharing of root complex integrated " ++ "endpoint %s isn't supported. ignoring.\n", ++ pci_name(pdev)); ++ return -ENOSYS; ++ case PCI_EXP_TYPE_ENDPOINT: ++ case PCI_EXP_TYPE_LEG_END: ++ break; ++ default: ++ printk(KERN_INFO ++ "PCI: io port sharing of non endpoint %s " ++ "doesn't make sense. ignoring.\n", ++ pci_name(pdev)); ++ return -EINVAL; ++ } ++ ++ kref_init(&slot->kref); ++ slot->switch_busnr = pci_dev_switch_busnr(pdev); ++ slot->segment = pci_domain_nr(pdev->bus); ++ slot->bus = pdev->bus->number; ++ slot->dev = PCI_SLOT(pdev->devfn); ++ ++ return 0; ++} ++ ++static struct pci_iomul_slot *__devinit ++pci_iomul_slot_alloc(struct pci_dev *pdev) ++{ ++ struct pci_iomul_slot *slot; ++ ++ slot = kzalloc(sizeof(*slot), GFP_KERNEL); ++ if (slot == NULL) ++ return NULL; ++ ++ if (pci_iomul_slot_init(pdev, slot) != 0) { ++ kfree(slot); ++ return NULL; ++ } ++ return slot; ++} ++ ++static void pci_iomul_slot_add_locked(struct pci_iomul_switch *sw, ++ struct pci_iomul_slot *slot) ++{ ++ BUG_ON(!mutex_is_locked(&sw->lock)); ++ list_add(&slot->sibling, &sw->slots); ++} ++ ++#ifdef CONFIG_HOTPLUG_PCI ++static void pci_iomul_slot_del_locked(struct pci_iomul_switch *sw, ++ struct pci_iomul_slot *slot) ++{ ++ BUG_ON(!mutex_is_locked(&sw->lock)); ++ list_del(&slot->sibling); ++} ++#endif ++ ++static void pci_iomul_slot_get(struct pci_iomul_slot *slot) ++{ ++ kref_get(&slot->kref); ++} ++ ++static void pci_iomul_slot_release(struct kref *kref) ++{ ++ struct pci_iomul_slot *slot = container_of(kref, struct pci_iomul_slot, ++ kref); ++ kfree(slot); ++} ++ ++static void pci_iomul_slot_put(struct pci_iomul_slot *slot) ++{ ++ kref_put(&slot->kref, &pci_iomul_slot_release); ++} ++ ++/*****************************************************************************/ ++static int pci_get_sbd(const char *str, ++ int *segment__, uint8_t *bus__, uint8_t *dev__) ++{ ++ int segment; ++ int bus; ++ int dev; ++ ++ if (sscanf(str, "%x:%x:%x", &segment, &bus, &dev) != 3) { ++ if (sscanf(str, "%x:%x", &bus, &dev) == 2) ++ segment = 0; ++ else ++ return -EINVAL; ++ } ++ ++ if (segment < 0 || INT_MAX <= segment) ++ return -EINVAL; ++ if (bus < 0 || PCI_BUS_MAX < bus) ++ return -EINVAL; ++ if (dev < 0 || PCI_DEV_MAX < dev) ++ return -EINVAL; ++ ++ *segment__ = segment; ++ *bus__ = bus; ++ *dev__ = dev; ++ return 0; ++} ++ ++static char iomul_param[COMMAND_LINE_SIZE]; ++#define TOKEN_MAX 10 /* SSSS:BB:DD length is 10 */ ++static int pci_is_iomul_dev_param(struct pci_dev *pdev) ++{ ++ int len; ++ char *p; ++ char *next_str; ++ ++ for (p = &iomul_param[0]; *p != '\0'; p = next_str + 1) { ++ next_str = strchr(p, ','); ++ if (next_str != NULL) ++ len = next_str - p; ++ else ++ len = strlen(p); ++ ++ if (len > 0 && len <= TOKEN_MAX) { ++ char tmp[TOKEN_MAX+1]; ++ int seg; ++ uint8_t bus; ++ uint8_t dev; ++ ++ strlcpy(tmp, p, len); ++ if (pci_get_sbd(tmp, &seg, &bus, &dev) == 0 && ++ pci_domain_nr(pdev->bus) == seg && ++ pdev->bus->number == bus && ++ PCI_SLOT(pdev->devfn) == dev) ++ return 1; ++ } ++ if (next_str == NULL) ++ break; ++ } ++ ++ /* check guestcev=+iomul option */ ++ return pci_is_iomuldev(pdev); ++} ++ ++/* ++ * Format: [:]:[,[:]:[,...] ++ */ ++static int __init pci_iomul_param_setup(char *str) ++{ ++ if (strlen(str) >= COMMAND_LINE_SIZE) ++ return 0; ++ ++ /* parse it after pci bus scanning */ ++ strlcpy(iomul_param, str, sizeof(iomul_param)); ++ return 1; ++} ++__setup("guestiomuldev=", pci_iomul_param_setup); ++ ++/*****************************************************************************/ ++static void __devinit pci_iomul_set_bridge_io_window(struct pci_dev *bridge, ++ uint32_t io_base, ++ uint32_t io_limit) ++{ ++ uint16_t l; ++ uint32_t upper16; ++ ++ io_base >>= 12; ++ io_base <<= 4; ++ io_limit >>= 12; ++ io_limit <<= 4; ++ l = (io_base & 0xff) | ((io_limit & 0xff) << 8); ++ upper16 = ((io_base & 0xffff00) >> 8) | ++ (((io_limit & 0xffff00) >> 8) << 16); ++ ++ /* Temporarily disable the I/O range before updating PCI_IO_BASE. */ ++ pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, 0x0000ffff); ++ /* Update lower 16 bits of I/O base/limit. */ ++ pci_write_config_word(bridge, PCI_IO_BASE, l); ++ /* Update upper 16 bits of I/O base/limit. */ ++ pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, upper16); ++} ++ ++static void __devinit pci_disable_bridge_io_window(struct pci_dev *bridge) ++{ ++ /* set base = 0xffffff limit = 0x0 */ ++ pci_iomul_set_bridge_io_window(bridge, 0xffffff, 0); ++} ++ ++static int __devinit pci_iomul_func_scan(struct pci_dev *pdev, ++ struct pci_iomul_slot *slot, ++ uint8_t func) ++{ ++ struct pci_iomul_func *f; ++ unsigned int i; ++ ++ f = kzalloc(sizeof(*f), GFP_KERNEL); ++ if (f == NULL) ++ return -ENOMEM; ++ ++ f->segment = slot->segment; ++ f->bus = slot->bus; ++ f->devfn = PCI_DEVFN(slot->dev, func); ++ f->io_size = pdev_size_io(pdev); ++ ++ for (i = 0; i < PCI_NUM_BARS; i++) { ++ if (!(pci_resource_flags(pdev, i) & IORESOURCE_IO)) ++ continue; ++ if (pci_resource_len(pdev, i) == 0) ++ continue; ++ ++ f->io_bar |= 1 << i; ++ f->resource[i] = pdev->resource[i]; ++ } ++ ++ if (f->io_bar) ++ slot->func[func] = f; ++ else ++ kfree(f); ++ return 0; ++} ++ ++/* ++ * This is tricky part. ++ * fake PCI resource assignment routines by setting flags to 0. ++ * PCI resource allocate routines think the resource should ++ * be allocated by checking flags. 0 means this resource isn't used. ++ * See pbus_size_io() and pdev_sort_resources(). ++ * ++ * After allocated resources, flags (IORESOURCE_IO) is exported ++ * to other part including user process. ++ * So we have to set flags to IORESOURCE_IO, but at the same time ++ * we must prevent those resources from reassigning when pci hot plug. ++ * To achieve that, set r->parent to dummy resource. ++ */ ++static void __devinit pci_iomul_disable_resource(struct resource *r) ++{ ++ /* don't allocate this resource */ ++ r->flags = 0; ++} ++ ++static void __devinit pci_iomul_reenable_resource( ++ struct resource *dummy_parent, struct resource *r) ++{ ++ int ret; ++ ++ dummy_parent->start = r->start; ++ dummy_parent->end = r->end; ++ dummy_parent->flags = r->flags; ++ dummy_parent->name = "PCI IOMUL dummy resource"; ++ ++ ret = request_resource(dummy_parent, r); ++ BUG_ON(ret); ++} ++ ++static void __devinit pci_iomul_fixup_ioresource(struct pci_dev *pdev, ++ struct pci_iomul_func *func, ++ int reassign, int dealloc) ++{ ++ uint8_t i; ++ struct resource *r; ++ ++ printk(KERN_INFO "PCI: deallocating io resource[%s]. io size 0x%lx\n", ++ pci_name(pdev), func->io_size); ++ for (i = 0; i < PCI_NUM_BARS; i++) { ++ r = &pdev->resource[i]; ++ if (!(func->io_bar & (1 << i))) ++ continue; ++ ++ if (reassign) { ++ r->end -= r->start; ++ r->start = 0; ++ pci_update_resource(pdev, i); ++ func->resource[i] = *r; ++ } ++ ++ if (dealloc) ++ /* don't allocate this resource */ ++ pci_iomul_disable_resource(r); ++ } ++ ++ /* parent PCI-PCI bridge */ ++ if (!reassign) ++ return; ++ pdev = pdev->bus->self; ++ if ((pdev->class >> 8) == PCI_CLASS_BRIDGE_HOST) ++ return; ++ pci_disable_bridge_io_window(pdev); ++ for (i = 0; i < PCI_NUM_RESOURCES; i++) { ++ r = &pdev->resource[i]; ++ if (!(r->flags & IORESOURCE_IO)) ++ continue; ++ ++ r->end -= r->start; ++ r->start = 0; ++ if (i < PCI_BRIDGE_RESOURCES) ++ pci_update_resource(pdev, i); ++ } ++} ++ ++static void __devinit __quirk_iomul_dealloc_ioresource( ++ struct pci_iomul_switch *sw, ++ struct pci_dev *pdev, struct pci_iomul_slot *slot) ++{ ++ struct pci_iomul_func *f; ++ struct pci_iomul_func *__f; ++ ++ if (pci_iomul_func_scan(pdev, slot, PCI_FUNC(pdev->devfn)) != 0) ++ return; ++ ++ f = slot->func[PCI_FUNC(pdev->devfn)]; ++ if (f == NULL) ++ return; ++ ++ __f = sw->func; ++ /* sw->io_base == 0 means that we are called at boot time. ++ * != 0 means that we are called by php after boot. */ ++ if (sw->io_base == 0 && ++ (__f == NULL || __f->io_size < f->io_size)) { ++ if (__f != NULL) { ++ struct pci_bus *__pbus; ++ struct pci_dev *__pdev; ++ ++ __pbus = pci_find_bus(__f->segment, __f->bus); ++ BUG_ON(__pbus == NULL); ++ __pdev = pci_get_slot(__pbus, __f->devfn); ++ BUG_ON(__pdev == NULL); ++ pci_iomul_fixup_ioresource(__pdev, __f, 0, 1); ++ pci_dev_put(__pdev); ++ } ++ ++ pci_iomul_fixup_ioresource(pdev, f, 1, 0); ++ sw->func = f; ++ } else { ++ pci_iomul_fixup_ioresource(pdev, f, 1, 1); ++ } ++} ++ ++static void __devinit quirk_iomul_dealloc_ioresource(struct pci_dev *pdev) ++{ ++ struct pci_iomul_switch *sw; ++ struct pci_iomul_slot *slot; ++ ++ if (pdev->hdr_type != PCI_HEADER_TYPE_NORMAL) ++ return; ++ if ((pdev->class >> 8) == PCI_CLASS_BRIDGE_HOST) ++ return; /* PCI Host Bridge isn't a target device */ ++ if (!pci_is_iomul_dev_param(pdev)) ++ return; ++ ++ mutex_lock(&switch_list_lock); ++ sw = pci_iomul_find_switch_locked(pci_domain_nr(pdev->bus), ++ pci_dev_switch_busnr(pdev)); ++ if (sw == NULL) { ++ sw = pci_iomul_switch_alloc(pci_domain_nr(pdev->bus), ++ pci_dev_switch_busnr(pdev)); ++ if (sw == NULL) { ++ mutex_unlock(&switch_list_lock); ++ printk(KERN_WARNING ++ "PCI: can't allocate memory " ++ "for sw of IO mulplexing %s", pci_name(pdev)); ++ return; ++ } ++ pci_iomul_switch_add_locked(sw); ++ } ++ pci_iomul_switch_get(sw); ++ mutex_unlock(&switch_list_lock); ++ ++ mutex_lock(&sw->lock); ++ slot = pci_iomul_find_slot_locked(sw, pdev->bus->number, ++ PCI_SLOT(pdev->devfn)); ++ if (slot == NULL) { ++ slot = pci_iomul_slot_alloc(pdev); ++ if (slot == NULL) { ++ mutex_unlock(&sw->lock); ++ pci_iomul_switch_put(sw); ++ printk(KERN_WARNING "PCI: can't allocate memory " ++ "for IO mulplexing %s", pci_name(pdev)); ++ return; ++ } ++ pci_iomul_slot_add_locked(sw, slot); ++ } ++ ++ printk(KERN_INFO "PCI: disable device and release io resource[%s].\n", ++ pci_name(pdev)); ++ pci_disable_device(pdev); ++ ++ __quirk_iomul_dealloc_ioresource(sw, pdev, slot); ++ ++ mutex_unlock(&sw->lock); ++ pci_iomul_switch_put(sw); ++} ++DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, ++ quirk_iomul_dealloc_ioresource); ++ ++static void __devinit pci_iomul_read_bridge_io(struct pci_iomul_switch *sw) ++{ ++ struct pci_iomul_func *f = sw->func; ++ ++ struct pci_bus *pbus; ++ struct pci_dev *pdev; ++ struct pci_dev *bridge; ++ ++ uint16_t l; ++ uint16_t base_upper16; ++ uint16_t limit_upper16; ++ uint32_t io_base; ++ uint32_t io_limit; ++ ++ pbus = pci_find_bus(f->segment, f->bus); ++ BUG_ON(pbus == NULL); ++ ++ pdev = pci_get_slot(pbus, f->devfn); ++ BUG_ON(pdev == NULL); ++ ++ bridge = pdev->bus->self; ++ pci_read_config_word(bridge, PCI_IO_BASE, &l); ++ pci_read_config_word(bridge, PCI_IO_BASE_UPPER16, &base_upper16); ++ pci_read_config_word(bridge, PCI_IO_LIMIT_UPPER16, &limit_upper16); ++ ++ io_base = (l & 0xf0) | ((uint32_t)base_upper16 << 8); ++ io_base <<= 8; ++ io_limit = (l >> 8) | ((uint32_t)limit_upper16 << 8); ++ io_limit <<= 8; ++ io_limit |= 0xfff; ++ ++ sw->io_base = io_base; ++ sw->io_limit = io_limit; ++ ++ pci_dev_put(pdev); ++ printk(KERN_INFO "PCI: bridge %s base 0x%x limit 0x%x\n", ++ pci_name(bridge), sw->io_base, sw->io_limit); ++} ++ ++static void __devinit pci_iomul_setup_brige(struct pci_dev *bridge, ++ uint32_t io_base, ++ uint32_t io_limit) ++{ ++ uint16_t cmd; ++ ++ if ((bridge->class >> 8) == PCI_CLASS_BRIDGE_HOST) ++ return; ++ ++ pci_iomul_set_bridge_io_window(bridge, io_base, io_limit); ++ ++ /* and forcibly enables IO */ ++ pci_read_config_word(bridge, PCI_COMMAND, &cmd); ++ if (!(cmd & PCI_COMMAND_IO)) { ++ cmd |= PCI_COMMAND_IO; ++ printk(KERN_INFO "PCI: Forcibly Enabling IO %s\n", ++ pci_name(bridge)); ++ pci_write_config_word(bridge, PCI_COMMAND, cmd); ++ } ++} ++ ++struct __bar { ++ unsigned long size; ++ uint8_t bar; ++}; ++ ++/* decending order */ ++static int __devinit pci_iomul_bar_cmp(const void *lhs__, const void *rhs__) ++{ ++ const struct __bar *lhs = (struct __bar*)lhs__; ++ const struct __bar *rhs = (struct __bar*)rhs__; ++ return - (lhs->size - rhs->size); ++} ++ ++static void __devinit pci_iomul_setup_dev(struct pci_dev *pdev, ++ struct pci_iomul_func *f, ++ uint32_t io_base) ++{ ++ struct __bar bars[PCI_NUM_BARS]; ++ int i; ++ uint8_t num_bars = 0; ++ struct resource *r; ++ ++ printk(KERN_INFO "PCI: Forcibly assign IO %s from 0x%x\n", ++ pci_name(pdev), io_base); ++ ++ for (i = 0; i < PCI_NUM_BARS; i++) { ++ if (!(f->io_bar & (1 << i))) ++ continue; ++ ++ r = &f->resource[i]; ++ bars[num_bars].size = pci_iomul_len(r); ++ bars[num_bars].bar = i; ++ ++ num_bars++; ++ } ++ ++ sort(bars, num_bars, sizeof(bars[0]), &pci_iomul_bar_cmp, NULL); ++ ++ for (i = 0; i < num_bars; i++) { ++ struct resource *fr = &f->resource[bars[i].bar]; ++ r = &pdev->resource[bars[i].bar]; ++ ++ BUG_ON(r->start != 0); ++ r->start += io_base; ++ r->end += io_base; ++ ++ fr->start = r->start; ++ fr->end = r->end; ++ ++ /* pci_update_resource() check flags. */ ++ r->flags = fr->flags; ++ pci_update_resource(pdev, bars[i].bar); ++ pci_iomul_reenable_resource(&f->dummy_parent, r); ++ ++ io_base += bars[i].size; ++ } ++} ++ ++static void __devinit pci_iomul_release_io_resource( ++ struct pci_dev *pdev, struct pci_iomul_switch *sw, ++ struct pci_iomul_slot *slot, struct pci_iomul_func *f) ++{ ++ int i; ++ struct resource *r; ++ ++ for (i = 0; i < PCI_NUM_BARS; i++) { ++ if (pci_resource_flags(pdev, i) & IORESOURCE_IO && ++ pdev->resource[i].parent != NULL) { ++ r = &pdev->resource[i]; ++ f->resource[i] = *r; ++ release_resource(r); ++ pci_iomul_reenable_resource(&f->dummy_parent, r); ++ } ++ } ++ ++ /* parent PCI-PCI bridge */ ++ pdev = pdev->bus->self; ++ if ((pdev->class >> 8) != PCI_CLASS_BRIDGE_HOST) { ++ for (i = PCI_BRIDGE_RESOURCES; i < PCI_NUM_RESOURCES; i++) { ++ struct resource *parent = pdev->resource[i].parent; ++ ++ if (pci_resource_flags(pdev, i) & IORESOURCE_IO && ++ parent != NULL) { ++ r = &pdev->resource[i]; ++ ++ sw->io_resource.flags = r->flags; ++ sw->io_resource.start = sw->io_base; ++ sw->io_resource.end = sw->io_limit; ++ sw->io_resource.name = "PCI IO Multiplexer"; ++ ++ release_resource(r); ++ pci_iomul_reenable_resource( ++ &slot->dummy_parent[i - PCI_BRIDGE_RESOURCES], r); ++ ++ if (request_resource(parent, ++ &sw->io_resource)) ++ printk(KERN_ERR ++ "PCI IOMul: can't allocate " ++ "resource. [0x%x, 0x%x]", ++ sw->io_base, sw->io_limit); ++ } ++ } ++ } ++} ++ ++static void __devinit quirk_iomul_reassign_ioresource(struct pci_dev *pdev) ++{ ++ struct pci_iomul_switch *sw; ++ struct pci_iomul_slot *slot; ++ struct pci_iomul_func *sf; ++ struct pci_iomul_func *f; ++ ++ pci_iomul_get_lock_switch(pdev, &sw, &slot); ++ if (sw == NULL || slot == NULL) ++ return; ++ ++ if (sw->io_base == 0) ++ pci_iomul_read_bridge_io(sw); ++ if (!pci_iomul_switch_io_allocated(sw)) ++ goto out; ++ ++ sf = sw->func; ++ f = slot->func[PCI_FUNC(pdev->devfn)]; ++ if (f == NULL) ++ /* (sf == NULL || f == NULL) case ++ * can happen when all the specified devices ++ * don't have io space ++ */ ++ goto out; ++ ++ if (sf != NULL && ++ (pci_domain_nr(pdev->bus) != sf->segment || ++ pdev->bus->number != sf->bus || ++ PCI_SLOT(pdev->devfn) != PCI_SLOT(sf->devfn)) && ++ PCI_FUNC(pdev->devfn) == 0) { ++ pci_iomul_setup_brige(pdev->bus->self, ++ sw->io_base, sw->io_limit); ++ } ++ ++ BUG_ON(f->io_size > sw->io_limit - sw->io_base + 1); ++ if (/* f == sf */ ++ sf != NULL && ++ pci_domain_nr(pdev->bus) == sf->segment && ++ pdev->bus->number == sf->bus && ++ pdev->devfn == sf->devfn) ++ pci_iomul_release_io_resource(pdev, sw, slot, f); ++ else ++ pci_iomul_setup_dev(pdev, f, sw->io_base); ++ ++out: ++ mutex_unlock(&sw->lock); ++ pci_iomul_switch_put(sw); ++} ++ ++DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, ++ quirk_iomul_reassign_ioresource); ++ ++/*****************************************************************************/ ++#ifdef CONFIG_HOTPLUG_PCI ++static int __devinit __pci_iomul_notifier_del_device(struct pci_dev *pdev) ++{ ++ struct pci_iomul_switch *sw; ++ struct pci_iomul_slot *slot; ++ int i; ++ ++ pci_iomul_get_lock_switch(pdev, &sw, &slot); ++ if (sw == NULL || slot == NULL) ++ return 0; ++ ++ if (sw->func == slot->func[PCI_FUNC(pdev->devfn)]) ++ sw->func = NULL; ++ kfree(slot->func[PCI_FUNC(pdev->devfn)]); ++ slot->func[PCI_FUNC(pdev->devfn)] = NULL; ++ for (i = 0; i < PCI_NUM_FUNC; i++) { ++ if (slot->func[i] != NULL) ++ goto out; ++ } ++ ++ pci_iomul_slot_del_locked(sw, slot); ++ pci_iomul_slot_put(slot); ++ ++out: ++ mutex_unlock(&sw->lock); ++ pci_iomul_switch_put(sw); ++ return 0; ++} ++ ++static int __devinit __pci_iomul_notifier_del_switch(struct pci_dev *pdev) ++{ ++ struct pci_iomul_switch *sw; ++ ++ mutex_lock(&switch_list_lock); ++ sw = pci_iomul_find_switch_locked(pci_domain_nr(pdev->bus), ++ pdev->bus->number); ++ if (sw == NULL) ++ goto out; ++ ++ pci_iomul_switch_del_locked(sw); ++ ++ mutex_lock(&sw->lock); ++ if (sw->io_resource.parent) ++ release_resource(&sw->io_resource); ++ sw->io_base = 0; /* to tell this switch is removed */ ++ sw->io_limit = 0; ++ BUG_ON(!list_empty(&sw->slots)); ++ mutex_unlock(&sw->lock); ++ ++out: ++ mutex_unlock(&switch_list_lock); ++ pci_iomul_switch_put(sw); ++ return 0; ++} ++ ++static int __devinit pci_iomul_notifier_del_device(struct pci_dev *pdev) ++{ ++ int ret; ++ switch (pdev->hdr_type) { ++ case PCI_HEADER_TYPE_NORMAL: ++ ret = __pci_iomul_notifier_del_device(pdev); ++ break; ++ case PCI_HEADER_TYPE_BRIDGE: ++ ret = __pci_iomul_notifier_del_switch(pdev); ++ break; ++ default: ++ printk(KERN_WARNING "PCI IOMUL: " ++ "device %s has unknown header type %02x, ignoring.\n", ++ pci_name(pdev), pdev->hdr_type); ++ ret = -EIO; ++ break; ++ } ++ return ret; ++} ++ ++static int __devinit pci_iomul_notifier(struct notifier_block *nb, ++ unsigned long action, void *data) ++{ ++ struct device *dev = data; ++ struct pci_dev *pdev = to_pci_dev(dev); ++ ++ switch (action) { ++ case BUS_NOTIFY_ADD_DEVICE: ++ quirk_iomul_reassign_ioresource(pdev); ++ break; ++ case BUS_NOTIFY_DEL_DEVICE: ++ return pci_iomul_notifier_del_device(pdev); ++ default: ++ /* nothing */ ++ break; ++ } ++ ++ return 0; ++} ++ ++static struct notifier_block pci_iomul_nb = { ++ .notifier_call = pci_iomul_notifier, ++}; ++ ++static int __init pci_iomul_hotplug_init(void) ++{ ++ bus_register_notifier(&pci_bus_type, &pci_iomul_nb); ++ return 0; ++} ++ ++late_initcall(pci_iomul_hotplug_init); ++#endif ++ ++/*****************************************************************************/ ++struct pci_iomul_data { ++ struct mutex lock; ++ ++ struct pci_dev *pdev; ++ struct pci_iomul_switch *sw; ++ struct pci_iomul_slot *slot; /* slot::kref */ ++ struct pci_iomul_func **func; /* when dereferencing, ++ sw->lock is necessary */ ++}; ++ ++static int pci_iomul_func_ioport(struct pci_iomul_func *func, ++ uint8_t bar, uint64_t offset, int *port) ++{ ++ if (!(func->io_bar & (1 << bar))) ++ return -EINVAL; ++ ++ *port = func->resource[bar].start + offset; ++ if (*port < func->resource[bar].start || ++ *port > func->resource[bar].end) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++static inline int pci_iomul_valid(struct pci_iomul_data *iomul) ++{ ++ BUG_ON(!mutex_is_locked(&iomul->lock)); ++ BUG_ON(!mutex_is_locked(&iomul->sw->lock)); ++ return pci_iomul_switch_io_allocated(iomul->sw) && ++ *iomul->func != NULL; ++} ++ ++static void __pci_iomul_enable_io(struct pci_dev *pdev) ++{ ++ uint16_t cmd; ++ ++ pci_dev_get(pdev); ++ pci_read_config_word(pdev, PCI_COMMAND, &cmd); ++ cmd |= PCI_COMMAND_IO; ++ pci_write_config_word(pdev, PCI_COMMAND, cmd); ++} ++ ++static void __pci_iomul_disable_io(struct pci_iomul_data *iomul, ++ struct pci_dev *pdev) ++{ ++ uint16_t cmd; ++ ++ if (!pci_iomul_valid(iomul)) ++ return; ++ ++ pci_read_config_word(pdev, PCI_COMMAND, &cmd); ++ cmd &= ~PCI_COMMAND_IO; ++ pci_write_config_word(pdev, PCI_COMMAND, cmd); ++ pci_dev_put(pdev); ++} ++ ++static int pci_iomul_open(struct inode *inode, struct file *filp) ++{ ++ struct pci_iomul_data *iomul; ++ iomul = kmalloc(sizeof(*iomul), GFP_KERNEL); ++ if (iomul == NULL) ++ return -ENOMEM; ++ ++ mutex_init(&iomul->lock); ++ iomul->pdev = NULL; ++ iomul->sw = NULL; ++ iomul->slot = NULL; ++ iomul->func = NULL; ++ filp->private_data = (void*)iomul; ++ ++ return 0; ++} ++ ++static int pci_iomul_release(struct inode *inode, struct file *filp) ++{ ++ struct pci_iomul_data *iomul = ++ (struct pci_iomul_data*)filp->private_data; ++ struct pci_iomul_switch *sw; ++ struct pci_iomul_slot *slot = NULL; ++ ++ mutex_lock(&iomul->lock); ++ sw = iomul->sw; ++ slot = iomul->slot; ++ if (iomul->pdev != NULL) { ++ if (sw != NULL) { ++ mutex_lock(&sw->lock); ++ if (sw->current_pdev == iomul->pdev) { ++ __pci_iomul_disable_io(iomul, ++ sw->current_pdev); ++ sw->current_pdev = NULL; ++ } ++ sw->count--; ++ if (sw->count == 0) { ++ release_region(sw->io_region->start, sw->io_region->end - sw->io_region->start + 1); ++ sw->io_region = NULL; ++ } ++ mutex_unlock(&sw->lock); ++ } ++ pci_dev_put(iomul->pdev); ++ } ++ mutex_unlock(&iomul->lock); ++ ++ if (slot != NULL) ++ pci_iomul_slot_put(slot); ++ if (sw != NULL) ++ pci_iomul_switch_put(sw); ++ kfree(iomul); ++ return 0; ++} ++ ++static long pci_iomul_setup(struct pci_iomul_data *iomul, ++ struct pci_iomul_setup __user *arg) ++{ ++ long error = 0; ++ struct pci_iomul_setup setup; ++ struct pci_iomul_switch *sw = NULL; ++ struct pci_iomul_slot *slot; ++ struct pci_bus *pbus; ++ struct pci_dev *pdev; ++ ++ if (copy_from_user(&setup, arg, sizeof(setup))) ++ return -EFAULT; ++ ++ pbus = pci_find_bus(setup.segment, setup.bus); ++ if (pbus == NULL) ++ return -ENODEV; ++ pdev = pci_get_slot(pbus, setup.dev); ++ if (pdev == NULL) ++ return -ENODEV; ++ ++ mutex_lock(&iomul->lock); ++ if (iomul->sw != NULL) { ++ error = -EBUSY; ++ goto out0; ++ } ++ ++ pci_iomul_get_lock_switch(pdev, &sw, &slot); ++ if (sw == NULL || slot == NULL) { ++ error = -ENODEV; ++ goto out0; ++ } ++ if (!pci_iomul_switch_io_allocated(sw)) { ++ error = -ENODEV; ++ goto out; ++ } ++ ++ if (slot->func[setup.func] == NULL) { ++ error = -ENODEV; ++ goto out; ++ } ++ ++ if (sw->count == 0) { ++ BUG_ON(sw->io_region != NULL); ++ sw->io_region = ++ request_region(sw->io_base, ++ sw->io_limit - sw->io_base + 1, ++ "PCI IO Multiplexer driver"); ++ if (sw->io_region == NULL) { ++ mutex_unlock(&sw->lock); ++ error = -EBUSY; ++ goto out; ++ } ++ } ++ sw->count++; ++ pci_iomul_slot_get(slot); ++ ++ iomul->pdev = pdev; ++ iomul->sw = sw; ++ iomul->slot = slot; ++ iomul->func = &slot->func[setup.func]; ++ ++out: ++ mutex_unlock(&sw->lock); ++out0: ++ mutex_unlock(&iomul->lock); ++ if (error != 0) { ++ if (sw != NULL) ++ pci_iomul_switch_put(sw); ++ pci_dev_put(pdev); ++ } ++ return error; ++} ++ ++static int pci_iomul_lock(struct pci_iomul_data *iomul, ++ struct pci_iomul_switch **sw, ++ struct pci_iomul_func **func) ++{ ++ mutex_lock(&iomul->lock); ++ *sw = iomul->sw; ++ if (*sw == NULL) { ++ mutex_unlock(&iomul->lock); ++ return -ENODEV; ++ } ++ mutex_lock(&(*sw)->lock); ++ if (!pci_iomul_valid(iomul)) { ++ mutex_unlock(&(*sw)->lock); ++ mutex_unlock(&iomul->lock); ++ return -ENODEV; ++ } ++ *func = *iomul->func; ++ ++ return 0; ++} ++ ++static long pci_iomul_disable_io(struct pci_iomul_data *iomul) ++{ ++ long error = 0; ++ struct pci_iomul_switch *sw; ++ struct pci_iomul_func *dummy_func; ++ struct pci_dev *pdev; ++ ++ if (pci_iomul_lock(iomul, &sw, &dummy_func) < 0) ++ return -ENODEV; ++ ++ pdev = iomul->pdev; ++ if (pdev == NULL) ++ error = -ENODEV; ++ ++ if (pdev != NULL && sw->current_pdev == pdev) { ++ __pci_iomul_disable_io(iomul, pdev); ++ sw->current_pdev = NULL; ++ } ++ ++ mutex_unlock(&sw->lock); ++ mutex_unlock(&iomul->lock); ++ return error; ++} ++ ++static void pci_iomul_switch_to( ++ struct pci_iomul_data *iomul, struct pci_iomul_switch *sw, ++ struct pci_dev *next_pdev) ++{ ++ if (sw->current_pdev == next_pdev) ++ /* nothing to do */ ++ return; ++ ++ if (sw->current_pdev != NULL) ++ __pci_iomul_disable_io(iomul, sw->current_pdev); ++ ++ __pci_iomul_enable_io(next_pdev); ++ sw->current_pdev = next_pdev; ++} ++ ++static long pci_iomul_in(struct pci_iomul_data *iomul, ++ struct pci_iomul_in __user *arg) ++{ ++ struct pci_iomul_in in; ++ struct pci_iomul_switch *sw; ++ struct pci_iomul_func *func; ++ ++ long error = 0; ++ int port; ++ uint32_t value = 0; ++ ++ if (copy_from_user(&in, arg, sizeof(in))) ++ return -EFAULT; ++ ++ if (pci_iomul_lock(iomul, &sw, &func) < 0) ++ return -ENODEV; ++ ++ error = pci_iomul_func_ioport(func, in.bar, in.offset, &port); ++ if (error) ++ goto out; ++ ++ pci_iomul_switch_to(iomul, sw, iomul->pdev); ++ switch (in.size) { ++ case 4: ++ value = inl(port); ++ break; ++ case 2: ++ value = inw(port); ++ break; ++ case 1: ++ value = inb(port); ++ break; ++ default: ++ error = -EINVAL; ++ break; ++ } ++ ++out: ++ mutex_unlock(&sw->lock); ++ mutex_unlock(&iomul->lock); ++ ++ if (error == 0 && put_user(value, &arg->value)) ++ return -EFAULT; ++ return error; ++} ++ ++static long pci_iomul_out(struct pci_iomul_data *iomul, ++ struct pci_iomul_out __user *arg) ++{ ++ struct pci_iomul_in out; ++ struct pci_iomul_switch *sw; ++ struct pci_iomul_func *func; ++ ++ long error = 0; ++ int port; ++ ++ if (copy_from_user(&out, arg, sizeof(out))) ++ return -EFAULT; ++ ++ if (pci_iomul_lock(iomul, &sw, &func) < 0) ++ return -ENODEV; ++ ++ error = pci_iomul_func_ioport(func, out.bar, out.offset, &port); ++ if (error) ++ goto out; ++ ++ pci_iomul_switch_to(iomul, sw, iomul->pdev); ++ switch (out.size) { ++ case 4: ++ outl(out.value, port); ++ break; ++ case 2: ++ outw(out.value, port); ++ break; ++ case 1: ++ outb(out.value, port); ++ break; ++ default: ++ error = -EINVAL; ++ break; ++ } ++ ++out: ++ mutex_unlock(&sw->lock); ++ mutex_unlock(&iomul->lock); ++ return error; ++} ++ ++static long pci_iomul_ioctl(struct file *filp, ++ unsigned int cmd, unsigned long arg) ++{ ++ long error; ++ struct pci_iomul_data *iomul = ++ (struct pci_iomul_data*)filp->private_data; ++ ++ if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) ++ return -EPERM; ++ ++ switch (cmd) { ++ case PCI_IOMUL_SETUP: ++ error = pci_iomul_setup(iomul, ++ (struct pci_iomul_setup __user *)arg); ++ break; ++ case PCI_IOMUL_DISABLE_IO: ++ error = pci_iomul_disable_io(iomul); ++ break; ++ case PCI_IOMUL_IN: ++ error = pci_iomul_in(iomul, (struct pci_iomul_in __user *)arg); ++ break; ++ case PCI_IOMUL_OUT: ++ error = pci_iomul_out(iomul, ++ (struct pci_iomul_out __user *)arg); ++ break; ++ default: ++ error = -ENOSYS; ++ break; ++ } ++ ++ return error; ++} ++ ++static const struct file_operations pci_iomul_fops = { ++ .owner = THIS_MODULE, ++ ++ .open = pci_iomul_open, /* nonseekable_open */ ++ .release = pci_iomul_release, ++ ++ .unlocked_ioctl = pci_iomul_ioctl, ++}; ++ ++static struct miscdevice pci_iomul_miscdev = { ++ .minor = MISC_DYNAMIC_MINOR, ++ .name = "pci_iomul", ++ .fops = &pci_iomul_fops, ++}; ++ ++static int pci_iomul_init(void) ++{ ++ int error; ++ error = misc_register(&pci_iomul_miscdev); ++ if (error != 0) { ++ printk(KERN_ALERT "Couldn't register /dev/misc/pci_iomul"); ++ return error; ++ } ++ printk("PCI IO multiplexer device installed.\n"); ++ return 0; ++} ++ ++#if 0 ++static void pci_iomul_cleanup(void) ++{ ++ misc_deregister(&pci_iomul_miscdev); ++} ++#endif ++ ++/* ++ * This must be called after pci fixup final which is called by ++ * device_initcall(pci_init). ++ */ ++late_initcall(pci_iomul_init); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Isaku Yamahata "); ++MODULE_DESCRIPTION("PCI IO space multiplexing driver"); +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/drivers/pci/iomulti.h 2009-12-04 10:27:46.000000000 +0100 +@@ -0,0 +1,51 @@ ++#ifndef PCI_IOMULTI_H ++#define PCI_IOMULTI_H ++/* ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ++ * ++ * Copyright (c) 2009 Isaku Yamahata ++ * VA Linux Systems Japan K.K. ++ * ++ */ ++ ++struct pci_iomul_setup { ++ uint16_t segment; ++ uint8_t bus; ++ uint8_t dev; ++ uint8_t func; ++}; ++ ++struct pci_iomul_in { ++ uint8_t bar; ++ uint64_t offset; ++ ++ uint8_t size; ++ uint32_t value; ++}; ++ ++struct pci_iomul_out { ++ uint8_t bar; ++ uint64_t offset; ++ ++ uint8_t size; ++ uint32_t value; ++}; ++ ++#define PCI_IOMUL_SETUP _IOW ('P', 0, struct pci_iomul_setup) ++#define PCI_IOMUL_DISABLE_IO _IO ('P', 1) ++#define PCI_IOMUL_IN _IOWR('P', 2, struct pci_iomul_in) ++#define PCI_IOMUL_OUT _IOW ('P', 3, struct pci_iomul_out) ++ ++#endif /* PCI_IOMULTI_H */ +--- sle11sp1-2010-03-22.orig/drivers/pci/pci.c 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/pci/pci.c 2010-03-22 12:11:11.000000000 +0100 +@@ -2680,6 +2680,13 @@ resource_size_t pci_specified_resource_a + */ + int pci_is_reassigndev(struct pci_dev *dev) + { ++#ifdef CONFIG_PCI_GUESTDEV ++ int result; ++ ++ result = pci_is_guestdev_to_reassign(dev); ++ if (result) ++ return result; ++#endif /* CONFIG_PCI_GUESTDEV */ + return (pci_specified_resource_alignment(dev) != 0); + } + +--- sle11sp1-2010-03-22.orig/drivers/pci/pci.h 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/pci/pci.h 2009-12-04 10:27:46.000000000 +0100 +@@ -311,4 +311,11 @@ static inline int pci_resource_alignment + return resource_alignment(res); + } + ++#ifdef CONFIG_PCI_GUESTDEV ++extern int pci_is_guestdev_to_reassign(struct pci_dev *dev); ++extern int pci_is_iomuldev(struct pci_dev *dev); ++#else ++#define pci_is_iomuldev(dev) 0 ++#endif ++ + #endif /* DRIVERS_PCI_H */ +--- sle11sp1-2010-03-22.orig/include/linux/acpi.h 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/include/linux/acpi.h 2009-12-04 10:27:46.000000000 +0100 +@@ -247,6 +247,8 @@ int acpi_check_region(resource_size_t st + int acpi_check_mem_region(resource_size_t start, resource_size_t n, + const char *name); + ++int acpi_pci_get_root_seg_bbn(char *hid, char *uid, int *seg, int *bbn); ++ + #ifdef CONFIG_PM_SLEEP + void __init acpi_no_s4_hw_signature(void); + void __init acpi_old_suspend_ordering(void); +--- sle11sp1-2010-03-22.orig/include/linux/pci.h 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/include/linux/pci.h 2010-03-22 12:11:20.000000000 +0100 +@@ -1330,5 +1330,11 @@ extern void pci_hp_create_module_link(st + extern void pci_hp_remove_module_link(struct pci_slot *pci_slot); + #endif + ++#ifdef CONFIG_PCI_GUESTDEV ++int pci_is_guestdev(struct pci_dev *dev); ++#else ++#define pci_is_guestdev(dev) 0 ++#endif ++ + #endif /* __KERNEL__ */ + #endif /* LINUX_PCI_H */ diff --git a/pci-reserve b/pci-reserve new file mode 100644 index 0000000..dc54558 --- /dev/null +++ b/pci-reserve @@ -0,0 +1,236 @@ +Subject: linux/pci: reserve io/memory space for bridge +From: http://xenbits.xensource.com/linux-2.6.18-xen.hg (tip 1010:10eae161c153) +Patch-mainline: n/a + +reserve io/memory space for bridge which will be used later +by PCI hotplug. + +Signed-off-by: Isaku Yamahata +Acked-by: jbeulich@novell.com + +--- sle11sp1-2010-03-11.orig/Documentation/kernel-parameters.txt 2010-03-11 09:11:45.000000000 +0100 ++++ sle11sp1-2010-03-11/Documentation/kernel-parameters.txt 2010-03-11 09:11:54.000000000 +0100 +@@ -1994,6 +1994,13 @@ and is between 256 and 4096 characters. + off: Turn ECRC off + on: Turn ECRC on. + ++ pci_reserve= [PCI] ++ Format: [[+IO][+MEM]][,...] ++ Format of sbdf: [:]:. ++ Specifies the least reserved io size or memory size ++ which is assigned to PCI bridge even when no child ++ pci device exists. This is useful with PCI hotplug. ++ + pcie_aspm= [PCIE] Forcibly enable or disable PCIe Active State Power + Management. + off Disable ASPM. +--- sle11sp1-2010-03-11.orig/drivers/pci/Kconfig 2009-12-04 10:27:46.000000000 +0100 ++++ sle11sp1-2010-03-11/drivers/pci/Kconfig 2009-12-04 10:27:49.000000000 +0100 +@@ -56,6 +56,13 @@ config PCI_IOMULTI + help + Say Y here if you need io multiplexing. + ++config PCI_RESERVE ++ bool "PCI IO/MEMORY space reserve" ++ depends on PCI && XEN_PRIVILEGED_GUEST ++ default y ++ help ++ Say Y here if you need PCI IO/MEMORY space reserve ++ + config PCI_STUB + tristate "PCI Stub driver" + depends on PCI +--- sle11sp1-2010-03-11.orig/drivers/pci/Makefile 2009-12-04 10:27:46.000000000 +0100 ++++ sle11sp1-2010-03-11/drivers/pci/Makefile 2009-12-04 10:27:49.000000000 +0100 +@@ -9,6 +9,7 @@ obj-$(CONFIG_PROC_FS) += proc.o + obj-$(CONFIG_SYSFS) += slot.o + obj-$(CONFIG_PCI_GUESTDEV) += guestdev.o + obj-$(CONFIG_PCI_IOMULTI) += iomulti.o ++obj-$(CONFIG_PCI_RESERVE) += reserve.o + + obj-$(CONFIG_PCI_LEGACY) += legacy.o + CFLAGS_legacy.o += -Wno-deprecated-declarations +--- sle11sp1-2010-03-11.orig/drivers/pci/pci.h 2009-12-04 10:27:46.000000000 +0100 ++++ sle11sp1-2010-03-11/drivers/pci/pci.h 2009-12-04 10:27:49.000000000 +0100 +@@ -318,4 +318,19 @@ extern int pci_is_iomuldev(struct pci_de + #define pci_is_iomuldev(dev) 0 + #endif + ++#ifdef CONFIG_PCI_RESERVE ++unsigned long pci_reserve_size_io(struct pci_bus *bus); ++unsigned long pci_reserve_size_mem(struct pci_bus *bus); ++#else ++static inline unsigned long pci_reserve_size_io(struct pci_bus *bus) ++{ ++ return 0; ++} ++ ++static inline unsigned long pci_reserve_size_mem(struct pci_bus *bus) ++{ ++ return 0; ++} ++#endif /* CONFIG_PCI_RESERVE */ ++ + #endif /* DRIVERS_PCI_H */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-11/drivers/pci/reserve.c 2010-03-24 14:00:05.000000000 +0100 +@@ -0,0 +1,138 @@ ++/* ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ++ * ++ * Copyright (c) 2009 Isaku Yamahata ++ * VA Linux Systems Japan K.K. ++ * ++ */ ++ ++#include ++#include ++ ++#include ++ ++static char pci_reserve_param[COMMAND_LINE_SIZE]; ++ ++/* pci_reserve= [PCI] ++ * Format: [[+IO][+MEM]][,...] ++ * Format of sbdf: [:]:. ++ */ ++static int pci_reserve_parse_size(const char *str, ++ unsigned long *io_size, ++ unsigned long *mem_size) ++{ ++ if (sscanf(str, "io%lx", io_size) == 1 || ++ sscanf(str, "IO%lx", io_size) == 1) ++ return 0; ++ ++ if (sscanf(str, "mem%lx", mem_size) == 1 || ++ sscanf(str, "MEM%lx", mem_size) == 1) ++ return 0; ++ ++ return -EINVAL; ++} ++ ++static int pci_reserve_parse_one(const char *str, ++ int *seg, int *bus, int *dev, int *func, ++ unsigned long *io_size, ++ unsigned long *mem_size) ++{ ++ char *p; ++ ++ *io_size = 0; ++ *mem_size = 0; ++ ++ if (sscanf(str, "%x:%x:%x.%x", seg, bus, dev, func) != 4) { ++ *seg = 0; ++ if (sscanf(str, "%x:%x.%x", bus, dev, func) != 3) { ++ return -EINVAL; ++ } ++ } ++ ++ p = strchr(str, '+'); ++ if (p == NULL) ++ return -EINVAL; ++ if (pci_reserve_parse_size(++p, io_size, mem_size)) ++ return -EINVAL; ++ ++ p = strchr(p, '+'); ++ return p ? pci_reserve_parse_size(p + 1, io_size, mem_size) : 0; ++} ++ ++static unsigned long pci_reserve_size(struct pci_bus *pbus, int flags) ++{ ++ char *sp; ++ char *ep; ++ ++ int seg; ++ int bus; ++ int dev; ++ int func; ++ ++ unsigned long io_size; ++ unsigned long mem_size; ++ ++ sp = pci_reserve_param; ++ ++ do { ++ ep = strchr(sp, ','); ++ if (ep) ++ *ep = '\0'; /* chomp */ ++ ++ if (pci_reserve_parse_one(sp, &seg, &bus, &dev, &func, ++ &io_size, &mem_size) == 0) { ++ if (pci_domain_nr(pbus) == seg && ++ pbus->number == bus && ++ PCI_SLOT(pbus->self->devfn) == dev && ++ PCI_FUNC(pbus->self->devfn) == func) { ++ switch (flags) { ++ case IORESOURCE_IO: ++ return io_size; ++ case IORESOURCE_MEM: ++ return mem_size; ++ default: ++ break; ++ } ++ } ++ } ++ ++ if (ep) { ++ *ep = ','; /* restore chomp'ed ',' for later */ ++ ep++; ++ } ++ sp = ep; ++ } while (ep); ++ ++ return 0; ++} ++ ++unsigned long pci_reserve_size_io(struct pci_bus *pbus) ++{ ++ return pci_reserve_size(pbus, IORESOURCE_IO); ++} ++ ++unsigned long pci_reserve_size_mem(struct pci_bus *pbus) ++{ ++ return pci_reserve_size(pbus, IORESOURCE_MEM); ++} ++ ++static int __init pci_reserve_setup(char *str) ++{ ++ if (strlen(str) >= sizeof(pci_reserve_param)) ++ return 0; ++ strlcpy(pci_reserve_param, str, sizeof(pci_reserve_param)); ++ return 1; ++} ++__setup("pci_reserve=", pci_reserve_setup); +--- sle11sp1-2010-03-11.orig/drivers/pci/setup-bus.c 2010-03-11 09:10:12.000000000 +0100 ++++ sle11sp1-2010-03-11/drivers/pci/setup-bus.c 2010-03-11 09:12:00.000000000 +0100 +@@ -337,7 +337,7 @@ static void pbus_size_io(struct pci_bus + #if defined(CONFIG_ISA) || defined(CONFIG_EISA) + size = (size & 0xff) + ((size & ~0xffUL) << 2); + #endif +- size = ALIGN(size + size1, 4096); ++ size = ALIGN(max(size + size1, pci_reserve_size_io(bus)), 4096); + if (!size) { + b_res->flags = 0; + return; +@@ -417,7 +417,8 @@ static int pbus_size_mem(struct pci_bus + min_align = align1 >> 1; + align += aligns[order]; + } +- size = ALIGN(size, min_align); ++ size = ALIGN(max(size, (resource_size_t)pci_reserve_size_mem(bus)), ++ min_align); + if (!size) { + b_res->flags = 0; + return 1; diff --git a/sfc-driverlink b/sfc-driverlink new file mode 100644 index 0000000..02f8f9d --- /dev/null +++ b/sfc-driverlink @@ -0,0 +1,1133 @@ +From: David Riddoch +commit d96c061bfd1839e34e136de0555564520acc97af +Author: Steve Hodgson +Date: Mon Jul 14 15:38:47 2008 +0100 + +Subject: sfc: Driverlink API for exporting hardware features to client drivers + +References: FATE#303479 +Acked-by: jbeulich@novell.com + +--- head-2009-11-06.orig/drivers/net/sfc/Makefile 2009-11-06 10:29:51.000000000 +0100 ++++ head-2009-11-06/drivers/net/sfc/Makefile 2009-07-28 10:04:25.000000000 +0200 +@@ -1,6 +1,7 @@ + sfc-y += efx.o falcon.o tx.o rx.o falcon_gmac.o \ + falcon_xmac.o selftest.o ethtool.o xfp_phy.o \ +- mdio_10g.o tenxpress.o boards.o sfe4001.o ++ mdio_10g.o tenxpress.o boards.o sfe4001.o \ ++ driverlink.o + sfc-$(CONFIG_SFC_MTD) += mtd.o + + obj-$(CONFIG_SFC) += sfc.o +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-11-06/drivers/net/sfc/driverlink.c 2009-07-28 10:04:25.000000000 +0200 +@@ -0,0 +1,367 @@ ++/**************************************************************************** ++ * Driver for Solarflare Solarstorm network controllers and boards ++ * Copyright 2005 Fen Systems Ltd. ++ * Copyright 2005-2008 Solarflare Communications Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ */ ++ ++#include ++#include ++#include ++#include ++#include "net_driver.h" ++#include "efx.h" ++#include "driverlink_api.h" ++#include "driverlink.h" ++ ++/* Protects @efx_driverlink_lock and @efx_driver_list */ ++static DEFINE_MUTEX(efx_driverlink_lock); ++ ++/* List of all registered drivers */ ++static LIST_HEAD(efx_driver_list); ++ ++/* List of all registered Efx ports */ ++static LIST_HEAD(efx_port_list); ++ ++/** ++ * Driver link handle used internally to track devices ++ * @efx_dev: driverlink device handle exported to consumers ++ * @efx: efx_nic backing the driverlink device ++ * @port_node: per-device list head ++ * @driver_node: per-driver list head ++ */ ++struct efx_dl_handle { ++ struct efx_dl_device efx_dev; ++ struct efx_nic *efx; ++ struct list_head port_node; ++ struct list_head driver_node; ++}; ++ ++static struct efx_dl_handle *efx_dl_handle(struct efx_dl_device *efx_dev) ++{ ++ return container_of(efx_dev, struct efx_dl_handle, efx_dev); ++} ++ ++/* Remove an Efx device, and call the driver's remove() callback if ++ * present. The caller must hold @efx_driverlink_lock. */ ++static void efx_dl_del_device(struct efx_dl_device *efx_dev) ++{ ++ struct efx_dl_handle *efx_handle = efx_dl_handle(efx_dev); ++ ++ EFX_INFO(efx_handle->efx, "%s driverlink client unregistering\n", ++ efx_dev->driver->name); ++ ++ if (efx_dev->driver->remove) ++ efx_dev->driver->remove(efx_dev); ++ ++ list_del(&efx_handle->driver_node); ++ list_del(&efx_handle->port_node); ++ ++ kfree(efx_handle); ++} ++ ++/* Attempt to probe the given device with the driver, creating a ++ * new &struct efx_dl_device. If the probe routine returns an error, ++ * then the &struct efx_dl_device is destroyed */ ++static void efx_dl_try_add_device(struct efx_nic *efx, ++ struct efx_dl_driver *driver) ++{ ++ struct efx_dl_handle *efx_handle; ++ struct efx_dl_device *efx_dev; ++ int rc; ++ ++ efx_handle = kzalloc(sizeof(*efx_handle), GFP_KERNEL); ++ if (!efx_handle) ++ goto fail; ++ efx_dev = &efx_handle->efx_dev; ++ efx_handle->efx = efx; ++ efx_dev->driver = driver; ++ efx_dev->pci_dev = efx->pci_dev; ++ INIT_LIST_HEAD(&efx_handle->port_node); ++ INIT_LIST_HEAD(&efx_handle->driver_node); ++ ++ rc = driver->probe(efx_dev, efx->net_dev, ++ efx->dl_info, efx->silicon_rev); ++ if (rc) ++ goto fail; ++ ++ list_add_tail(&efx_handle->driver_node, &driver->device_list); ++ list_add_tail(&efx_handle->port_node, &efx->dl_device_list); ++ ++ EFX_INFO(efx, "%s driverlink client registered\n", driver->name); ++ return; ++ ++ fail: ++ EFX_INFO(efx, "%s driverlink client skipped\n", driver->name); ++ ++ kfree(efx_handle); ++} ++ ++/* Unregister a driver from the driverlink layer, calling the ++ * driver's remove() callback for every attached device */ ++void efx_dl_unregister_driver(struct efx_dl_driver *driver) ++{ ++ struct efx_dl_handle *efx_handle, *efx_handle_n; ++ ++ printk(KERN_INFO "Efx driverlink unregistering %s driver\n", ++ driver->name); ++ ++ mutex_lock(&efx_driverlink_lock); ++ ++ list_for_each_entry_safe(efx_handle, efx_handle_n, ++ &driver->device_list, driver_node) ++ efx_dl_del_device(&efx_handle->efx_dev); ++ ++ list_del(&driver->node); ++ ++ mutex_unlock(&efx_driverlink_lock); ++} ++EXPORT_SYMBOL(efx_dl_unregister_driver); ++ ++/* Register a new driver with the driverlink layer. The driver's ++ * probe routine will be called for every attached nic. */ ++int efx_dl_register_driver(struct efx_dl_driver *driver) ++{ ++ struct efx_nic *efx; ++ int rc; ++ ++ printk(KERN_INFO "Efx driverlink registering %s driver\n", ++ driver->name); ++ ++ INIT_LIST_HEAD(&driver->node); ++ INIT_LIST_HEAD(&driver->device_list); ++ ++ rc = mutex_lock_interruptible(&efx_driverlink_lock); ++ if (rc) ++ return rc; ++ ++ list_add_tail(&driver->node, &efx_driver_list); ++ list_for_each_entry(efx, &efx_port_list, dl_node) ++ efx_dl_try_add_device(efx, driver); ++ ++ mutex_unlock(&efx_driverlink_lock); ++ ++ return 0; ++} ++EXPORT_SYMBOL(efx_dl_register_driver); ++ ++void efx_dl_unregister_nic(struct efx_nic *efx) ++{ ++ struct efx_dl_handle *efx_handle, *efx_handle_n; ++ ++ mutex_lock(&efx_driverlink_lock); ++ ++ list_for_each_entry_safe_reverse(efx_handle, efx_handle_n, ++ &efx->dl_device_list, ++ port_node) ++ efx_dl_del_device(&efx_handle->efx_dev); ++ ++ list_del(&efx->dl_node); ++ ++ mutex_unlock(&efx_driverlink_lock); ++} ++ ++int efx_dl_register_nic(struct efx_nic *efx) ++{ ++ struct efx_dl_driver *driver; ++ int rc; ++ ++ rc = mutex_lock_interruptible(&efx_driverlink_lock); ++ if (rc) ++ return rc; ++ ++ list_add_tail(&efx->dl_node, &efx_port_list); ++ list_for_each_entry(driver, &efx_driver_list, node) ++ efx_dl_try_add_device(efx, driver); ++ ++ mutex_unlock(&efx_driverlink_lock); ++ ++ return 0; ++} ++ ++/* Dummy callback implementations. ++ * To avoid a branch point on the fast-path, the callbacks are always ++ * implemented - they are never NULL. ++ */ ++static enum efx_veto efx_dummy_tx_packet_callback(struct efx_dl_device *efx_dev, ++ struct sk_buff *skb) ++{ ++ return EFX_ALLOW_PACKET; ++} ++ ++static enum efx_veto efx_dummy_rx_packet_callback(struct efx_dl_device *efx_dev, ++ const char *pkt_buf, int len) ++{ ++ return EFX_ALLOW_PACKET; ++} ++ ++static int efx_dummy_request_mtu_callback(struct efx_dl_device *efx_dev, ++ int new_mtu) ++{ ++ return 0; ++} ++ ++static void efx_dummy_mtu_changed_callback(struct efx_dl_device *efx_dev, ++ int mtu) ++{ ++ return; ++} ++ ++static void efx_dummy_event_callback(struct efx_dl_device *efx_dev, void *event) ++{ ++ return; ++} ++ ++struct efx_dl_callbacks efx_default_callbacks = { ++ .tx_packet = efx_dummy_tx_packet_callback, ++ .rx_packet = efx_dummy_rx_packet_callback, ++ .request_mtu = efx_dummy_request_mtu_callback, ++ .mtu_changed = efx_dummy_mtu_changed_callback, ++ .event = efx_dummy_event_callback, ++}; ++ ++void efx_dl_unregister_callbacks(struct efx_dl_device *efx_dev, ++ struct efx_dl_callbacks *callbacks) ++{ ++ struct efx_dl_handle *efx_handle = efx_dl_handle(efx_dev); ++ struct efx_nic *efx = efx_handle->efx; ++ ++ efx_suspend(efx); ++ ++ EFX_INFO(efx, "removing callback hooks into %s driver\n", ++ efx_dev->driver->name); ++ ++ if (callbacks->tx_packet) { ++ BUG_ON(efx->dl_cb_dev.tx_packet != efx_dev); ++ efx->dl_cb.tx_packet = efx_default_callbacks.tx_packet; ++ efx->dl_cb_dev.tx_packet = NULL; ++ } ++ if (callbacks->rx_packet) { ++ BUG_ON(efx->dl_cb_dev.rx_packet != efx_dev); ++ efx->dl_cb.rx_packet = efx_default_callbacks.rx_packet; ++ efx->dl_cb_dev.rx_packet = NULL; ++ } ++ if (callbacks->request_mtu) { ++ BUG_ON(efx->dl_cb_dev.request_mtu != efx_dev); ++ efx->dl_cb.request_mtu = efx_default_callbacks.request_mtu; ++ efx->dl_cb_dev.request_mtu = NULL; ++ } ++ if (callbacks->mtu_changed) { ++ BUG_ON(efx->dl_cb_dev.mtu_changed != efx_dev); ++ efx->dl_cb.mtu_changed = efx_default_callbacks.mtu_changed; ++ efx->dl_cb_dev.mtu_changed = NULL; ++ } ++ if (callbacks->event) { ++ BUG_ON(efx->dl_cb_dev.event != efx_dev); ++ efx->dl_cb.event = efx_default_callbacks.event; ++ efx->dl_cb_dev.event = NULL; ++ } ++ ++ efx_resume(efx); ++} ++EXPORT_SYMBOL(efx_dl_unregister_callbacks); ++ ++int efx_dl_register_callbacks(struct efx_dl_device *efx_dev, ++ struct efx_dl_callbacks *callbacks) ++{ ++ struct efx_dl_handle *efx_handle = efx_dl_handle(efx_dev); ++ struct efx_nic *efx = efx_handle->efx; ++ int rc = 0; ++ ++ efx_suspend(efx); ++ ++ /* Check that the requested callbacks are not already hooked. */ ++ if ((callbacks->tx_packet && efx->dl_cb_dev.tx_packet) || ++ (callbacks->rx_packet && efx->dl_cb_dev.rx_packet) || ++ (callbacks->request_mtu && efx->dl_cb_dev.request_mtu) || ++ (callbacks->mtu_changed && efx->dl_cb_dev.mtu_changed) || ++ (callbacks->event && efx->dl_cb_dev.event)) { ++ rc = -EBUSY; ++ goto out; ++ } ++ ++ EFX_INFO(efx, "adding callback hooks to %s driver\n", ++ efx_dev->driver->name); ++ ++ /* Hook in the requested callbacks, leaving any NULL members ++ * referencing the members of @efx_default_callbacks */ ++ if (callbacks->tx_packet) { ++ efx->dl_cb.tx_packet = callbacks->tx_packet; ++ efx->dl_cb_dev.tx_packet = efx_dev; ++ } ++ if (callbacks->rx_packet) { ++ efx->dl_cb.rx_packet = callbacks->rx_packet; ++ efx->dl_cb_dev.rx_packet = efx_dev; ++ } ++ if (callbacks->request_mtu) { ++ efx->dl_cb.request_mtu = callbacks->request_mtu; ++ efx->dl_cb_dev.request_mtu = efx_dev; ++ } ++ if (callbacks->mtu_changed) { ++ efx->dl_cb.mtu_changed = callbacks->mtu_changed; ++ efx->dl_cb_dev.mtu_changed = efx_dev; ++ } ++ if (callbacks->event) { ++ efx->dl_cb.event = callbacks->event; ++ efx->dl_cb_dev.event = efx_dev; ++ } ++ ++ out: ++ efx_resume(efx); ++ ++ return rc; ++} ++EXPORT_SYMBOL(efx_dl_register_callbacks); ++ ++void efx_dl_schedule_reset(struct efx_dl_device *efx_dev) ++{ ++ struct efx_dl_handle *efx_handle = efx_dl_handle(efx_dev); ++ struct efx_nic *efx = efx_handle->efx; ++ ++ efx_schedule_reset(efx, RESET_TYPE_ALL); ++} ++EXPORT_SYMBOL(efx_dl_schedule_reset); ++ ++void efx_dl_reset_unlock(void) ++{ ++ mutex_unlock(&efx_driverlink_lock); ++} ++ ++/* Suspend ready for reset, serialising against all the driverlink interfacse ++ * and calling the suspend() callback of every registered driver */ ++void efx_dl_reset_suspend(struct efx_nic *efx) ++{ ++ struct efx_dl_handle *efx_handle; ++ struct efx_dl_device *efx_dev; ++ ++ mutex_lock(&efx_driverlink_lock); ++ ++ list_for_each_entry_reverse(efx_handle, ++ &efx->dl_device_list, ++ port_node) { ++ efx_dev = &efx_handle->efx_dev; ++ if (efx_dev->driver->reset_suspend) ++ efx_dev->driver->reset_suspend(efx_dev); ++ } ++} ++ ++/* Resume after a reset, calling the resume() callback of every registered ++ * driver, and releasing @Efx_driverlink_lock acquired in ++ * efx_dl_reset_resume() */ ++void efx_dl_reset_resume(struct efx_nic *efx, int ok) ++{ ++ struct efx_dl_handle *efx_handle; ++ struct efx_dl_device *efx_dev; ++ ++ list_for_each_entry(efx_handle, &efx->dl_device_list, ++ port_node) { ++ efx_dev = &efx_handle->efx_dev; ++ if (efx_dev->driver->reset_resume) ++ efx_dev->driver->reset_resume(efx_dev, ok); ++ } ++ ++ mutex_unlock(&efx_driverlink_lock); ++} +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-11-06/drivers/net/sfc/driverlink.h 2009-07-28 10:04:25.000000000 +0200 +@@ -0,0 +1,43 @@ ++/**************************************************************************** ++ * Driver for Solarflare Solarstorm network controllers and boards ++ * Copyright 2005 Fen Systems Ltd. ++ * Copyright 2006-2008 Solarflare Communications Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ */ ++ ++#ifndef EFX_DRIVERLINK_H ++#define EFX_DRIVERLINK_H ++ ++/* Forward declarations */ ++struct efx_dl_device; ++struct efx_nic; ++ ++/* Efx callback devices ++ * ++ * A list of the devices that own each callback. The partner to ++ * struct efx_dl_callbacks. ++ */ ++struct efx_dl_cb_devices { ++ struct efx_dl_device *tx_packet; ++ struct efx_dl_device *rx_packet; ++ struct efx_dl_device *request_mtu; ++ struct efx_dl_device *mtu_changed; ++ struct efx_dl_device *event; ++}; ++ ++extern struct efx_dl_callbacks efx_default_callbacks; ++ ++#define EFX_DL_CALLBACK(_port, _name, ...) \ ++ (_port)->dl_cb._name((_port)->dl_cb_dev._name, __VA_ARGS__) ++ ++extern int efx_dl_register_nic(struct efx_nic *efx); ++extern void efx_dl_unregister_nic(struct efx_nic *efx); ++ ++/* Suspend and resume client drivers over a hardware reset */ ++extern void efx_dl_reset_suspend(struct efx_nic *efx); ++extern void efx_dl_reset_resume(struct efx_nic *efx, int ok); ++ ++#endif /* EFX_DRIVERLINK_H */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-11-06/drivers/net/sfc/driverlink_api.h 2009-07-28 10:04:25.000000000 +0200 +@@ -0,0 +1,303 @@ ++/**************************************************************************** ++ * Driver for Solarflare Solarstorm network controllers and boards ++ * Copyright 2005-2006 Fen Systems Ltd. ++ * Copyright 2005-2008 Solarflare Communications Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ */ ++ ++#ifndef EFX_DRIVERLINK_API_H ++#define EFX_DRIVERLINK_API_H ++ ++#include ++ ++/* Forward declarations */ ++struct pci_dev; ++struct net_device; ++struct sk_buff; ++struct efx_dl_device; ++struct efx_dl_device_info; ++ ++/* An extra safeguard in addition to symbol versioning */ ++#define EFX_DRIVERLINK_API_VERSION 2 ++ ++/** ++ * struct efx_dl_driver - An Efx driverlink device driver ++ * ++ * A driverlink client defines and initializes as many instances of ++ * efx_dl_driver as required, registering each one with ++ * efx_dl_register_driver(). ++ * ++ * @name: Name of the driver ++ * @probe: Called when device added ++ * The client should use the @def_info linked list and @silicon_rev ++ * to determine if they wish to attach to this device. ++ * Context: process, driverlink semaphore held ++ * @remove: Called when device removed ++ * The client must ensure the finish all operations with this ++ * device before returning from this method. ++ * Context: process, driverlink semaphore held ++ * @reset_suspend: Called before device is reset ++ * Called immediately before a hardware reset. The client must stop all ++ * hardware processing before returning from this method. Callbacks will ++ * be inactive when this method is called. ++ * Context: process, driverlink semaphore held. rtnl_lock may be held ++ * @reset_resume: Called after device is reset ++ * Called after a hardware reset. If @ok is true, the client should ++ * state and resume normal operations. If @ok is false, the client should ++ * abandon use of the hardware resources. remove() will still be called. ++ * Context: process, driverlink semaphore held. rtnl_lock may be held ++ */ ++struct efx_dl_driver { ++ const char *name; ++ ++ int (*probe) (struct efx_dl_device *efx_dl_dev, ++ const struct net_device *net_dev, ++ const struct efx_dl_device_info *dev_info, ++ const char *silicon_rev); ++ void (*remove) (struct efx_dl_device *efx_dev); ++ void (*reset_suspend) (struct efx_dl_device *efx_dev); ++ void (*reset_resume) (struct efx_dl_device *efx_dev, int ok); ++ ++/* private: */ ++ struct list_head node; ++ struct list_head device_list; ++}; ++ ++/** ++ * enum efx_dl_device_info_type - Device information identifier. ++ * ++ * Used to identify each item in the &struct efx_dl_device_info linked list ++ * provided to each driverlink client in the probe() @dev_info member. ++ * ++ * @EFX_DL_FALCON_RESOURCES: Information type is &struct efx_dl_falcon_resources ++ */ ++enum efx_dl_device_info_type { ++ /** Falcon resources available for export */ ++ EFX_DL_FALCON_RESOURCES = 0, ++}; ++ ++/** ++ * struct efx_dl_device_info - device information structure ++ * ++ * @next: Link to next structure, if any ++ * @type: Type code for this structure ++ */ ++struct efx_dl_device_info { ++ struct efx_dl_device_info *next; ++ enum efx_dl_device_info_type type; ++}; ++ ++/** ++ * enum efx_dl_falcon_resource_flags - Falcon resource information flags. ++ * ++ * Flags that describe hardware variations for the current Falcon device. ++ * ++ * @EFX_DL_FALCON_DUAL_FUNC: Port is dual-function. ++ * Certain silicon revisions have two pci functions, and require ++ * certain hardware resources to be accessed via the secondary ++ * function ++ * @EFX_DL_FALCON_USE_MSI: Port is initialised to use MSI/MSI-X interrupts. ++ * Falcon supports traditional legacy interrupts and MSI/MSI-X ++ * interrupts. The choice is made at run time by the sfc driver, and ++ * notified to the clients by this enumeration ++ */ ++enum efx_dl_falcon_resource_flags { ++ EFX_DL_FALCON_DUAL_FUNC = 0x1, ++ EFX_DL_FALCON_USE_MSI = 0x2, ++}; ++ ++/** ++ * struct efx_dl_falcon_resources - Falcon resource information. ++ * ++ * This structure describes Falcon hardware resources available for ++ * use by a driverlink driver. ++ * ++ * @hdr: Resource linked list header ++ * @biu_lock: Register access lock. ++ * Some Falcon revisions require register access for configuration ++ * registers to be serialised between ports and PCI functions. ++ * The sfc driver will provide the appropriate lock semantics for ++ * the underlying hardware. ++ * @buffer_table_min: First available buffer table entry ++ * @buffer_table_lim: Last available buffer table entry + 1 ++ * @evq_timer_min: First available event queue with timer ++ * @evq_timer_lim: Last available event queue with timer + 1 ++ * @evq_int_min: First available event queue with interrupt ++ * @evq_int_lim: Last available event queue with interrupt + 1 ++ * @rxq_min: First available RX queue ++ * @rxq_lim: Last available RX queue + 1 ++ * @txq_min: First available TX queue ++ * @txq_lim: Last available TX queue + 1 ++ * @flags: Hardware variation flags ++ */ ++struct efx_dl_falcon_resources { ++ struct efx_dl_device_info hdr; ++ spinlock_t *biu_lock; ++ unsigned buffer_table_min; ++ unsigned buffer_table_lim; ++ unsigned evq_timer_min; ++ unsigned evq_timer_lim; ++ unsigned evq_int_min; ++ unsigned evq_int_lim; ++ unsigned rxq_min; ++ unsigned rxq_lim; ++ unsigned txq_min; ++ unsigned txq_lim; ++ enum efx_dl_falcon_resource_flags flags; ++}; ++ ++/** ++ * struct efx_dl_device - An Efx driverlink device. ++ * ++ * @pci_dev: PCI device used by the sfc driver. ++ * @priv: Driver private data ++ * Driverlink clients can use this to store a pointer to their ++ * internal per-device data structure. Each (driver, device) ++ * tuple has a separate &struct efx_dl_device, so clients can use ++ * this @priv field independently. ++ * @driver: Efx driverlink driver for this device ++ */ ++struct efx_dl_device { ++ struct pci_dev *pci_dev; ++ void *priv; ++ struct efx_dl_driver *driver; ++}; ++ ++/** ++ * enum efx_veto - Packet veto request flag. ++ * ++ * This is the return type for the rx_packet() and tx_packet() methods ++ * in &struct efx_dl_callbacks. ++ * ++ * @EFX_ALLOW_PACKET: Packet may be transmitted/received ++ * @EFX_VETO_PACKET: Packet must not be transmitted/received ++ */ ++enum efx_veto { ++ EFX_ALLOW_PACKET = 0, ++ EFX_VETO_PACKET = 1, ++}; ++ ++/** ++ * struct efx_dl_callbacks - Efx callbacks ++ * ++ * This is a tighly controlled set of simple callbacks, that are attached ++ * to the sfc driver via efx_dl_register_callbacks(). They export just enough ++ * state to allow clients to make use of the available hardware resources. ++ * ++ * For efficiency, only one client can hook each callback. Since these ++ * callbacks are called on packet transmit and reception paths, and the ++ * sfc driver may have multiple tx and rx queues per port, clients should ++ * avoid acquiring locks or allocating memory. ++ * ++ * @tx_packet: Called when packet is about to be transmitted ++ * Called for every packet about to be transmitted, providing means ++ * for the client to snoop traffic, and veto transmission by returning ++ * %EFX_VETO_PACKET (the sfc driver will subsequently free the skb). ++ * Context: tasklet, netif_tx_lock held ++ * @rx_packet: Called when packet is received ++ * Called for every received packet (after LRO), allowing the client ++ * to snoop every received packet (on every rx queue), and veto ++ * reception by returning %EFX_VETO_PACKET. ++ * Context: tasklet ++ * @request_mtu: Called to request MTU change. ++ * Called whenever the user requests the net_dev mtu to be changed. ++ * If the client returns an error, the mtu change is aborted. The sfc ++ * driver guarantees that no other callbacks are running. ++ * Context: process, rtnl_lock held. ++ * @mtu_changed: Called when MTU has been changed. ++ * Called after the mtu has been successfully changed, always after ++ * a previous call to request_mtu(). The sfc driver guarantees that no ++ * other callbacks are running. ++ * Context: process, rtnl_lock held. ++ * @event: Called when a hardware NIC event is not understood by the sfc driver. ++ * Context: tasklet. ++ */ ++struct efx_dl_callbacks { ++ enum efx_veto (*tx_packet) (struct efx_dl_device *efx_dev, ++ struct sk_buff *skb); ++ enum efx_veto (*rx_packet) (struct efx_dl_device *efx_dev, ++ const char *pkt_hdr, int pkt_len); ++ int (*request_mtu) (struct efx_dl_device *efx_dev, int new_mtu); ++ void (*mtu_changed) (struct efx_dl_device *efx_dev, int mtu); ++ void (*event) (struct efx_dl_device *efx_dev, void *p_event); ++}; ++ ++/* Include API version number in symbol used for efx_dl_register_driver */ ++#define efx_dl_stringify_1(x, y) x ## y ++#define efx_dl_stringify_2(x, y) efx_dl_stringify_1(x, y) ++#define efx_dl_register_driver \ ++ efx_dl_stringify_2(efx_dl_register_driver_api_ver_, \ ++ EFX_DRIVERLINK_API_VERSION) ++ ++/* Exported driverlink api used to register and unregister the client driver ++ * and any callbacks [only one per port allowed], and to allow a client driver ++ * to request reset to recover from an error condition. ++ * ++ * All of these functions acquire the driverlink semaphore, so must not be ++ * called from an efx_dl_driver or efx_dl_callbacks member, and must be called ++ * from process context. ++ */ ++extern int efx_dl_register_driver(struct efx_dl_driver *driver); ++ ++extern void efx_dl_unregister_driver(struct efx_dl_driver *driver); ++ ++extern int efx_dl_register_callbacks(struct efx_dl_device *efx_dev, ++ struct efx_dl_callbacks *callbacks); ++ ++extern void efx_dl_unregister_callbacks(struct efx_dl_device *efx_dev, ++ struct efx_dl_callbacks *callbacks); ++ ++/* Schedule a reset without grabbing any locks */ ++extern void efx_dl_schedule_reset(struct efx_dl_device *efx_dev); ++ ++/** ++ * efx_dl_for_each_device_info_matching - iterate an efx_dl_device_info list ++ * @_dev_info: Pointer to first &struct efx_dl_device_info ++ * @_type: Type code to look for ++ * @_info_type: Structure type corresponding to type code ++ * @_field: Name of &struct efx_dl_device_info field in the type ++ * @_p: Iterator variable ++ * ++ * Example: ++ * struct efx_dl_falcon_resources *res; ++ * efx_dl_for_each_device_info_matching(dev_info, EFX_DL_FALCON_RESOURCES, ++ * struct efx_dl_falcon_resources, ++ * hdr, res) { ++ * if (res->flags & EFX_DL_FALCON_DUAL_FUNC) ++ * .... ++ * } ++ */ ++#define efx_dl_for_each_device_info_matching(_dev_info, _type, \ ++ _info_type, _field, _p) \ ++ for ((_p) = container_of((_dev_info), _info_type, _field); \ ++ (_p) != NULL; \ ++ (_p) = container_of((_p)->_field.next, _info_type, _field))\ ++ if ((_p)->_field.type != _type) \ ++ continue; \ ++ else ++ ++/** ++ * efx_dl_search_device_info - search an efx_dl_device_info list ++ * @_dev_info: Pointer to first &struct efx_dl_device_info ++ * @_type: Type code to look for ++ * @_info_type: Structure type corresponding to type code ++ * @_field: Name of &struct efx_dl_device_info member in this type ++ * @_p: Result variable ++ * ++ * Example: ++ * struct efx_dl_falcon_resources *res; ++ * efx_dl_search_device_info(dev_info, EFX_DL_FALCON_RESOURCES, ++ * struct efx_dl_falcon_resources, hdr, res); ++ * if (res) ++ * .... ++ */ ++#define efx_dl_search_device_info(_dev_info, _type, _info_type, \ ++ _field, _p) \ ++ efx_dl_for_each_device_info_matching((_dev_info), (_type), \ ++ _info_type, _field, (_p)) \ ++ break; ++ ++#endif /* EFX_DRIVERLINK_API_H */ +--- head-2009-11-06.orig/drivers/net/sfc/efx.c 2009-11-06 10:29:51.000000000 +0100 ++++ head-2009-11-06/drivers/net/sfc/efx.c 2009-10-12 13:40:25.000000000 +0200 +@@ -1487,12 +1487,21 @@ static int efx_change_mtu(struct net_dev + + efx_stop_all(efx); + ++ /* Ask driverlink client if we can change MTU */ ++ rc = EFX_DL_CALLBACK(efx, request_mtu, new_mtu); ++ if (rc) ++ goto out; ++ + EFX_LOG(efx, "changing MTU to %d\n", new_mtu); + + efx_fini_channels(efx); + net_dev->mtu = new_mtu; + efx_init_channels(efx); + ++ /* Notify driverlink client of new MTU */ ++ EFX_DL_CALLBACK(efx, mtu_changed, new_mtu); ++ ++ out: + efx_start_all(efx); + return rc; + } +@@ -1680,6 +1689,23 @@ static void efx_unregister_netdev(struct + * Device reset and suspend + * + **************************************************************************/ ++/* Serialise access to the driverlink callbacks, by quiescing event processing ++ * (without flushing the descriptor queues), and acquiring the rtnl_lock */ ++void efx_suspend(struct efx_nic *efx) ++{ ++ EFX_LOG(efx, "suspending operations\n"); ++ ++ rtnl_lock(); ++ efx_stop_all(efx); ++} ++ ++void efx_resume(struct efx_nic *efx) ++{ ++ EFX_LOG(efx, "resuming operations\n"); ++ ++ efx_start_all(efx); ++ rtnl_unlock(); ++} + + /* Tears down the entire software state and most of the hardware state + * before reset. */ +@@ -1760,8 +1786,8 @@ static int efx_reset(struct efx_nic *efx + enum reset_type method = efx->reset_pending; + int rc = 0; + +- /* Serialise with kernel interfaces */ + rtnl_lock(); ++ efx_dl_reset_suspend(efx); + + /* If we're not RUNNING then don't reset. Leave the reset_pending + * flag set so that efx_pci_probe_main will be retried */ +@@ -1807,6 +1833,7 @@ out_disable: + } + + out_unlock: ++ efx_dl_reset_resume(efx, 1); + rtnl_unlock(); + return rc; + } +@@ -1951,6 +1978,9 @@ static int efx_init_struct(struct efx_ni + efx->mac_op = &efx_dummy_mac_operations; + efx->phy_op = &efx_dummy_phy_operations; + efx->mdio.dev = net_dev; ++ INIT_LIST_HEAD(&efx->dl_node); ++ INIT_LIST_HEAD(&efx->dl_device_list); ++ efx->dl_cb = efx_default_callbacks; + INIT_WORK(&efx->phy_work, efx_phy_work); + INIT_WORK(&efx->mac_work, efx_mac_work); + atomic_set(&efx->netif_stop_count, 1); +@@ -2054,6 +2084,7 @@ static void efx_pci_remove(struct pci_de + efx = pci_get_drvdata(pci_dev); + if (!efx) + return; ++ efx_dl_unregister_nic(efx); + + /* Mark the NIC as fini, then stop the interface */ + rtnl_lock(); +@@ -2230,9 +2261,16 @@ static int __devinit efx_pci_probe(struc + if (rc) + goto fail5; + ++ /* Register with driverlink layer */ ++ rc = efx_dl_register_nic(efx); ++ if (rc) ++ goto fail6; ++ + EFX_LOG(efx, "initialisation successful\n"); + return 0; + ++ fail6: ++ efx_unregister_netdev(efx); + fail5: + efx_pci_remove_main(efx); + fail4: +--- head-2009-11-06.orig/drivers/net/sfc/falcon.c 2009-11-06 10:29:51.000000000 +0100 ++++ head-2009-11-06/drivers/net/sfc/falcon.c 2009-07-28 10:04:25.000000000 +0200 +@@ -36,14 +36,14 @@ + + /** + * struct falcon_nic_data - Falcon NIC state +- * @next_buffer_table: First available buffer table id ++ * @resources: Resource information for driverlink client + * @pci_dev2: The secondary PCI device if present + * @i2c_data: Operations and state for I2C bit-bashing algorithm + * @int_error_count: Number of internal errors seen recently + * @int_error_expire: Time at which error count will be expired + */ + struct falcon_nic_data { +- unsigned next_buffer_table; ++ struct efx_dl_falcon_resources resources; + struct pci_dev *pci_dev2; + struct i2c_algo_bit_data i2c_data; + +@@ -336,8 +336,8 @@ static int falcon_alloc_special_buffer(s + memset(buffer->addr, 0xff, len); + + /* Select new buffer ID */ +- buffer->index = nic_data->next_buffer_table; +- nic_data->next_buffer_table += buffer->entries; ++ buffer->index = nic_data->resources.buffer_table_min; ++ nic_data->resources.buffer_table_min += buffer->entries; + + EFX_LOG(efx, "allocating special buffers %d-%d at %llx+%x " + "(virt %p phys %llx)\n", buffer->index, +@@ -960,10 +960,12 @@ static void falcon_handle_driver_event(s + case TX_DESCQ_FLS_DONE_EV_DECODE: + EFX_TRACE(efx, "channel %d TXQ %d flushed\n", + channel->channel, ev_sub_data); ++ EFX_DL_CALLBACK(efx, event, event); + break; + case RX_DESCQ_FLS_DONE_EV_DECODE: + EFX_TRACE(efx, "channel %d RXQ %d flushed\n", + channel->channel, ev_sub_data); ++ EFX_DL_CALLBACK(efx, event, event); + break; + case EVQ_INIT_DONE_EV_DECODE: + EFX_LOG(efx, "channel %d EVQ %d initialised\n", +@@ -972,14 +974,17 @@ static void falcon_handle_driver_event(s + case SRM_UPD_DONE_EV_DECODE: + EFX_TRACE(efx, "channel %d SRAM update done\n", + channel->channel); ++ EFX_DL_CALLBACK(efx, event, event); + break; + case WAKE_UP_EV_DECODE: + EFX_TRACE(efx, "channel %d RXQ %d wakeup event\n", + channel->channel, ev_sub_data); ++ EFX_DL_CALLBACK(efx, event, event); + break; + case TIMER_EV_DECODE: + EFX_TRACE(efx, "channel %d RX queue %d timer expired\n", + channel->channel, ev_sub_data); ++ EFX_DL_CALLBACK(efx, event, event); + break; + case RX_RECOVERY_EV_DECODE: + EFX_ERR(efx, "channel %d seen DRIVER RX_RESET event. " +@@ -1004,6 +1009,7 @@ static void falcon_handle_driver_event(s + EFX_TRACE(efx, "channel %d unknown driver event code %d " + "data %04x\n", channel->channel, ev_sub_code, + ev_sub_data); ++ EFX_DL_CALLBACK(efx, event, event); + break; + } + } +@@ -2744,6 +2750,59 @@ static int falcon_probe_nvconfig(struct + return rc; + } + ++/* Looks at available SRAM resources and silicon revision, and works out ++ * how many queues we can support, and where things like descriptor caches ++ * should live. */ ++static int falcon_dimension_resources(struct efx_nic *efx) ++{ ++ unsigned internal_dcs_entries; ++ struct falcon_nic_data *nic_data = efx->nic_data; ++ struct efx_dl_falcon_resources *res = &nic_data->resources; ++ ++ /* Fill out the driverlink resource list */ ++ res->hdr.type = EFX_DL_FALCON_RESOURCES; ++ res->biu_lock = &efx->biu_lock; ++ efx->dl_info = &res->hdr; ++ ++ /* NB. The minimum values get increased as this driver initialises ++ * its resources, so this should prevent any overlap. ++ */ ++ switch (falcon_rev(efx)) { ++ case FALCON_REV_A1: ++ res->rxq_min = 16; ++ res->txq_min = 16; ++ res->evq_int_min = 4; ++ res->evq_int_lim = 5; ++ res->evq_timer_min = 5; ++ res->evq_timer_lim = 4096; ++ internal_dcs_entries = 8192; ++ break; ++ case FALCON_REV_B0: ++ default: ++ res->rxq_min = 0; ++ res->txq_min = 0; ++ res->evq_int_min = 0; ++ res->evq_int_lim = 64; ++ res->evq_timer_min = 64; ++ res->evq_timer_lim = 4096; ++ internal_dcs_entries = 4096; ++ break; ++ } ++ ++ /* Internal SRAM only for now */ ++ res->rxq_lim = internal_dcs_entries / RX_DC_ENTRIES; ++ res->txq_lim = internal_dcs_entries / TX_DC_ENTRIES; ++ res->buffer_table_lim = 8192; ++ ++ if (FALCON_IS_DUAL_FUNC(efx)) ++ res->flags |= EFX_DL_FALCON_DUAL_FUNC; ++ ++ if (EFX_INT_MODE_USE_MSI(efx)) ++ res->flags |= EFX_DL_FALCON_USE_MSI; ++ ++ return 0; ++} ++ + /* Probe the NIC variant (revision, ASIC vs FPGA, function count, port + * count, port speed). Set workaround and feature flags accordingly. + */ +@@ -2771,9 +2830,11 @@ static int falcon_probe_nic_variant(stru + EFX_ERR(efx, "Falcon rev A1 PCI-X not supported\n"); + return -ENODEV; + } ++ efx->silicon_rev = "falcon/a1"; + break; + + case FALCON_REV_B0: ++ efx->silicon_rev = "falcon/b0"; + break; + + default: +@@ -2883,6 +2944,10 @@ int falcon_probe_nic(struct efx_nic *efx + if (rc) + goto fail5; + ++ rc = falcon_dimension_resources(efx); ++ if (rc) ++ goto fail6; ++ + /* Initialise I2C adapter */ + efx->i2c_adap.owner = THIS_MODULE; + nic_data->i2c_data = falcon_i2c_bit_operations; +@@ -2892,10 +2957,12 @@ int falcon_probe_nic(struct efx_nic *efx + strlcpy(efx->i2c_adap.name, "SFC4000 GPIO", sizeof(efx->i2c_adap.name)); + rc = i2c_bit_add_bus(&efx->i2c_adap); + if (rc) +- goto fail5; ++ goto fail6; + + return 0; + ++ fail6: ++ efx->dl_info = NULL; + fail5: + falcon_remove_spi_devices(efx); + falcon_free_buffer(efx, &efx->irq_status); +@@ -3083,6 +3150,7 @@ void falcon_remove_nic(struct efx_nic *e + /* Tear down the private nic state */ + kfree(efx->nic_data); + efx->nic_data = NULL; ++ efx->dl_info = NULL; + } + + void falcon_update_nic_stats(struct efx_nic *efx) +--- head-2009-11-06.orig/drivers/net/sfc/net_driver.h 2009-11-06 10:29:51.000000000 +0100 ++++ head-2009-11-06/drivers/net/sfc/net_driver.h 2009-07-28 10:04:25.000000000 +0200 +@@ -29,6 +29,8 @@ + + #include "enum.h" + #include "bitfield.h" ++#include "driverlink_api.h" ++#include "driverlink.h" + + /************************************************************************** + * +@@ -754,6 +756,12 @@ union efx_multicast_hash { + * @loopback_mode: Loopback status + * @loopback_modes: Supported loopback mode bitmask + * @loopback_selftest: Offline self-test private state ++ * @silicon_rev: Silicon revision description for driverlink ++ * @dl_info: Linked list of hardware parameters exposed through driverlink ++ * @dl_node: Driverlink port list ++ * @dl_device_list: Driverlink device list ++ * @dl_cb: Driverlink callbacks table ++ * @dl_cb_dev: Driverlink callback owner devices + * + * The @priv field of the corresponding &struct net_device points to + * this. +@@ -844,6 +852,13 @@ struct efx_nic { + unsigned int loopback_modes; + + void *loopback_selftest; ++ ++ const char *silicon_rev; ++ struct efx_dl_device_info *dl_info; ++ struct list_head dl_node; ++ struct list_head dl_device_list; ++ struct efx_dl_callbacks dl_cb; ++ struct efx_dl_cb_devices dl_cb_dev; + }; + + static inline int efx_dev_registered(struct efx_nic *efx) +--- head-2009-11-06.orig/drivers/net/sfc/rx.c 2009-11-06 10:29:51.000000000 +0100 ++++ head-2009-11-06/drivers/net/sfc/rx.c 2009-11-06 10:32:03.000000000 +0100 +@@ -447,7 +447,21 @@ static void efx_rx_packet_lro(struct efx + struct efx_rx_buffer *rx_buf, + bool checksummed) + { ++ struct efx_nic *efx = channel->efx; + struct napi_struct *napi = &channel->napi_str; ++ enum efx_veto veto; ++ ++ /* It would be faster if we had access to packets at the ++ * other side of generic LRO. Unfortunately, there isn't ++ * an obvious interface to this, so veto packets before LRO */ ++ veto = EFX_DL_CALLBACK(efx, rx_packet, rx_buf->data, rx_buf->len); ++ if (unlikely(veto)) { ++ EFX_TRACE(efx, "LRO RX vetoed by driverlink %s driver\n", ++ efx->dl_cb_dev.rx_packet->driver->name); ++ /* Free the buffer now */ ++ efx_free_rx_buffer(efx, rx_buf); ++ return; ++ } + + /* Pass the skb/page into the LRO engine */ + if (rx_buf->page) { +@@ -550,6 +564,7 @@ void __efx_rx_packet(struct efx_channel + struct efx_rx_buffer *rx_buf, bool checksummed) + { + struct efx_nic *efx = channel->efx; ++ enum efx_veto veto; + struct sk_buff *skb; + + /* If we're in loopback test, then pass the packet directly to the +@@ -561,6 +576,16 @@ void __efx_rx_packet(struct efx_channel + goto done; + } + ++ /* Allow callback to veto the packet */ ++ veto = EFX_DL_CALLBACK(efx, rx_packet, rx_buf->data, rx_buf->len); ++ if (unlikely(veto)) { ++ EFX_LOG(efx, "RX vetoed by driverlink %s driver\n", ++ efx->dl_cb_dev.rx_packet->driver->name); ++ /* Free the buffer now */ ++ efx_free_rx_buffer(efx, rx_buf); ++ goto done; ++ } ++ + if (rx_buf->skb) { + prefetch(skb_shinfo(rx_buf->skb)); + +--- head-2009-11-06.orig/drivers/net/sfc/tx.c 2009-11-06 10:29:51.000000000 +0100 ++++ head-2009-11-06/drivers/net/sfc/tx.c 2009-10-12 13:40:32.000000000 +0200 +@@ -374,6 +374,7 @@ netdev_tx_t efx_hard_start_xmit(struct s + { + struct efx_nic *efx = netdev_priv(net_dev); + struct efx_tx_queue *tx_queue; ++ enum efx_veto veto; + + if (unlikely(efx->port_inhibited)) + return NETDEV_TX_BUSY; +@@ -383,6 +384,17 @@ netdev_tx_t efx_hard_start_xmit(struct s + else + tx_queue = &efx->tx_queue[EFX_TX_QUEUE_NO_CSUM]; + ++ /* See if driverlink wants to veto the packet. */ ++ veto = EFX_DL_CALLBACK(efx, tx_packet, skb); ++ if (unlikely(veto)) { ++ EFX_TRACE(efx, "TX queue %d packet vetoed by " ++ "driverlink %s driver\n", tx_queue->queue, ++ efx->dl_cb_dev.tx_packet->driver->name); ++ /* Free the skb; nothing else will do it */ ++ dev_kfree_skb_any(skb); ++ return NETDEV_TX_OK; ++ } ++ + return efx_xmit(efx, tx_queue, skb); + } + diff --git a/sfc-driverlink-conditional b/sfc-driverlink-conditional new file mode 100644 index 0000000..5ca60cb --- /dev/null +++ b/sfc-driverlink-conditional @@ -0,0 +1,248 @@ +From: jbeulich@novell.com +Subject: conditionalize driverlink additions to Solarflare driver +Patch-mainline: obsolete +References: FATE#303479 + +At once converted the EFX_TRACE() invocations after vetoed RX/TX +callbacks to ...LOG() ones, which is consistent with Solarflare's +current code according to David Riddoch (2008-09-12). + +--- head-2009-11-06.orig/drivers/net/sfc/Kconfig 2009-04-21 11:02:22.000000000 +0200 ++++ head-2009-11-06/drivers/net/sfc/Kconfig 2009-10-12 13:41:03.000000000 +0200 +@@ -12,8 +12,12 @@ config SFC + To compile this driver as a module, choose M here. The module + will be called sfc. + ++config SFC_DRIVERLINK ++ bool ++ + config SFC_RESOURCE + depends on SFC && X86 ++ select SFC_DRIVERLINK + tristate "Solarflare Solarstorm SFC4000 resource driver" + help + This module provides the SFC resource manager driver. +--- head-2009-11-06.orig/drivers/net/sfc/Makefile 2009-02-06 12:42:18.000000000 +0100 ++++ head-2009-11-06/drivers/net/sfc/Makefile 2009-10-12 13:41:03.000000000 +0200 +@@ -1,7 +1,7 @@ + sfc-y += efx.o falcon.o tx.o rx.o falcon_gmac.o \ + falcon_xmac.o selftest.o ethtool.o xfp_phy.o \ +- mdio_10g.o tenxpress.o boards.o sfe4001.o \ +- driverlink.o ++ mdio_10g.o tenxpress.o boards.o sfe4001.o ++sfc-$(CONFIG_SFC_DRIVERLINK) += driverlink.o + sfc-$(CONFIG_SFC_MTD) += mtd.o + + obj-$(CONFIG_SFC) += sfc.o +--- head-2009-11-06.orig/drivers/net/sfc/driverlink.c 2009-07-28 10:04:25.000000000 +0200 ++++ head-2009-11-06/drivers/net/sfc/driverlink.c 2009-10-12 13:41:03.000000000 +0200 +@@ -14,7 +14,6 @@ + #include + #include "net_driver.h" + #include "efx.h" +-#include "driverlink_api.h" + #include "driverlink.h" + + /* Protects @efx_driverlink_lock and @efx_driver_list */ +--- head-2009-11-06.orig/drivers/net/sfc/driverlink.h 2009-07-28 10:04:25.000000000 +0200 ++++ head-2009-11-06/drivers/net/sfc/driverlink.h 2009-10-12 13:41:03.000000000 +0200 +@@ -15,6 +15,10 @@ + struct efx_dl_device; + struct efx_nic; + ++#ifdef CONFIG_SFC_DRIVERLINK ++ ++#include "driverlink_api.h" ++ + /* Efx callback devices + * + * A list of the devices that own each callback. The partner to +@@ -40,4 +44,23 @@ extern void efx_dl_unregister_nic(struct + extern void efx_dl_reset_suspend(struct efx_nic *efx); + extern void efx_dl_reset_resume(struct efx_nic *efx, int ok); + ++#define EFX_DL_LOG EFX_LOG ++ ++#else /* CONFIG_SFC_DRIVERLINK */ ++ ++enum efx_veto { EFX_ALLOW_PACKET = 0 }; ++ ++static inline int efx_nop_callback(struct efx_nic *efx) { return 0; } ++#define EFX_DL_CALLBACK(port, name, ...) efx_nop_callback(port) ++ ++static inline int efx_dl_register_nic(struct efx_nic *efx) { return 0; } ++static inline void efx_dl_unregister_nic(struct efx_nic *efx) {} ++ ++static inline void efx_dl_reset_suspend(struct efx_nic *efx) {} ++static inline void efx_dl_reset_resume(struct efx_nic *efx, int ok) {} ++ ++#define EFX_DL_LOG(efx, fmt, args...) ((void)(efx)) ++ ++#endif /* CONFIG_SFC_DRIVERLINK */ ++ + #endif /* EFX_DRIVERLINK_H */ +--- head-2009-11-06.orig/drivers/net/sfc/efx.c 2009-10-12 13:40:25.000000000 +0200 ++++ head-2009-11-06/drivers/net/sfc/efx.c 2009-10-12 13:41:03.000000000 +0200 +@@ -1689,6 +1689,7 @@ static void efx_unregister_netdev(struct + * Device reset and suspend + * + **************************************************************************/ ++#ifdef CONFIG_SFC_DRIVERLINK + /* Serialise access to the driverlink callbacks, by quiescing event processing + * (without flushing the descriptor queues), and acquiring the rtnl_lock */ + void efx_suspend(struct efx_nic *efx) +@@ -1706,6 +1707,7 @@ void efx_resume(struct efx_nic *efx) + efx_start_all(efx); + rtnl_unlock(); + } ++#endif + + /* Tears down the entire software state and most of the hardware state + * before reset. */ +@@ -1978,9 +1980,11 @@ static int efx_init_struct(struct efx_ni + efx->mac_op = &efx_dummy_mac_operations; + efx->phy_op = &efx_dummy_phy_operations; + efx->mdio.dev = net_dev; ++#ifdef CONFIG_SFC_DRIVERLINK + INIT_LIST_HEAD(&efx->dl_node); + INIT_LIST_HEAD(&efx->dl_device_list); + efx->dl_cb = efx_default_callbacks; ++#endif + INIT_WORK(&efx->phy_work, efx_phy_work); + INIT_WORK(&efx->mac_work, efx_mac_work); + atomic_set(&efx->netif_stop_count, 1); +--- head-2009-11-06.orig/drivers/net/sfc/falcon.c 2009-07-28 10:04:25.000000000 +0200 ++++ head-2009-11-06/drivers/net/sfc/falcon.c 2009-10-12 13:41:03.000000000 +0200 +@@ -36,6 +36,7 @@ + + /** + * struct falcon_nic_data - Falcon NIC state ++ * @next_buffer_table: First available buffer table id + * @resources: Resource information for driverlink client + * @pci_dev2: The secondary PCI device if present + * @i2c_data: Operations and state for I2C bit-bashing algorithm +@@ -43,7 +44,11 @@ + * @int_error_expire: Time at which error count will be expired + */ + struct falcon_nic_data { ++#ifndef CONFIG_SFC_DRIVERLINK ++ unsigned next_buffer_table; ++#else + struct efx_dl_falcon_resources resources; ++#endif + struct pci_dev *pci_dev2; + struct i2c_algo_bit_data i2c_data; + +@@ -336,8 +341,13 @@ static int falcon_alloc_special_buffer(s + memset(buffer->addr, 0xff, len); + + /* Select new buffer ID */ ++#ifndef CONFIG_SFC_DRIVERLINK ++ buffer->index = nic_data->next_buffer_table; ++ nic_data->next_buffer_table += buffer->entries; ++#else + buffer->index = nic_data->resources.buffer_table_min; + nic_data->resources.buffer_table_min += buffer->entries; ++#endif + + EFX_LOG(efx, "allocating special buffers %d-%d at %llx+%x " + "(virt %p phys %llx)\n", buffer->index, +@@ -2755,6 +2765,7 @@ static int falcon_probe_nvconfig(struct + * should live. */ + static int falcon_dimension_resources(struct efx_nic *efx) + { ++#ifdef CONFIG_SFC_DRIVERLINK + unsigned internal_dcs_entries; + struct falcon_nic_data *nic_data = efx->nic_data; + struct efx_dl_falcon_resources *res = &nic_data->resources; +@@ -2799,6 +2810,7 @@ static int falcon_dimension_resources(st + + if (EFX_INT_MODE_USE_MSI(efx)) + res->flags |= EFX_DL_FALCON_USE_MSI; ++#endif + + return 0; + } +@@ -2962,7 +2974,9 @@ int falcon_probe_nic(struct efx_nic *efx + return 0; + + fail6: ++#ifdef CONFIG_SFC_DRIVERLINK + efx->dl_info = NULL; ++#endif + fail5: + falcon_remove_spi_devices(efx); + falcon_free_buffer(efx, &efx->irq_status); +@@ -3150,7 +3164,9 @@ void falcon_remove_nic(struct efx_nic *e + /* Tear down the private nic state */ + kfree(efx->nic_data); + efx->nic_data = NULL; ++#ifdef CONFIG_SFC_DRIVERLINK + efx->dl_info = NULL; ++#endif + } + + void falcon_update_nic_stats(struct efx_nic *efx) +--- head-2009-11-06.orig/drivers/net/sfc/net_driver.h 2009-07-28 10:04:25.000000000 +0200 ++++ head-2009-11-06/drivers/net/sfc/net_driver.h 2009-10-12 13:41:03.000000000 +0200 +@@ -29,7 +29,6 @@ + + #include "enum.h" + #include "bitfield.h" +-#include "driverlink_api.h" + #include "driverlink.h" + + /************************************************************************** +@@ -854,11 +853,13 @@ struct efx_nic { + void *loopback_selftest; + + const char *silicon_rev; ++#ifdef CONFIG_SFC_DRIVERLINK + struct efx_dl_device_info *dl_info; + struct list_head dl_node; + struct list_head dl_device_list; + struct efx_dl_callbacks dl_cb; + struct efx_dl_cb_devices dl_cb_dev; ++#endif + }; + + static inline int efx_dev_registered(struct efx_nic *efx) +--- head-2009-11-06.orig/drivers/net/sfc/rx.c 2009-11-06 10:32:03.000000000 +0100 ++++ head-2009-11-06/drivers/net/sfc/rx.c 2009-11-06 10:32:24.000000000 +0100 +@@ -456,8 +456,8 @@ static void efx_rx_packet_lro(struct efx + * an obvious interface to this, so veto packets before LRO */ + veto = EFX_DL_CALLBACK(efx, rx_packet, rx_buf->data, rx_buf->len); + if (unlikely(veto)) { +- EFX_TRACE(efx, "LRO RX vetoed by driverlink %s driver\n", +- efx->dl_cb_dev.rx_packet->driver->name); ++ EFX_DL_LOG(efx, "LRO RX vetoed by driverlink %s driver\n", ++ efx->dl_cb_dev.rx_packet->driver->name); + /* Free the buffer now */ + efx_free_rx_buffer(efx, rx_buf); + return; +@@ -579,8 +579,8 @@ void __efx_rx_packet(struct efx_channel + /* Allow callback to veto the packet */ + veto = EFX_DL_CALLBACK(efx, rx_packet, rx_buf->data, rx_buf->len); + if (unlikely(veto)) { +- EFX_LOG(efx, "RX vetoed by driverlink %s driver\n", +- efx->dl_cb_dev.rx_packet->driver->name); ++ EFX_DL_LOG(efx, "RX vetoed by driverlink %s driver\n", ++ efx->dl_cb_dev.rx_packet->driver->name); + /* Free the buffer now */ + efx_free_rx_buffer(efx, rx_buf); + goto done; +--- head-2009-11-06.orig/drivers/net/sfc/tx.c 2009-10-12 13:40:32.000000000 +0200 ++++ head-2009-11-06/drivers/net/sfc/tx.c 2009-10-12 13:41:03.000000000 +0200 +@@ -387,9 +387,9 @@ netdev_tx_t efx_hard_start_xmit(struct s + /* See if driverlink wants to veto the packet. */ + veto = EFX_DL_CALLBACK(efx, tx_packet, skb); + if (unlikely(veto)) { +- EFX_TRACE(efx, "TX queue %d packet vetoed by " +- "driverlink %s driver\n", tx_queue->queue, +- efx->dl_cb_dev.tx_packet->driver->name); ++ EFX_DL_LOG(efx, "TX queue %d packet vetoed by " ++ "driverlink %s driver\n", tx_queue->queue, ++ efx->dl_cb_dev.tx_packet->driver->name); + /* Free the skb; nothing else will do it */ + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; diff --git a/sfc-endianness b/sfc-endianness new file mode 100644 index 0000000..4ad1fb5 --- /dev/null +++ b/sfc-endianness @@ -0,0 +1,18 @@ +From: jbeulich@novell.com +Subject: fix building with gcc 4.4 +Patch-mainline: obsolete + +--- head-2009-05-19.orig/drivers/net/sfc/sfc_resource/ci/efhw/hardware_sysdep.h 2008-07-17 16:18:07.000000000 +0200 ++++ head-2009-05-19/drivers/net/sfc/sfc_resource/ci/efhw/hardware_sysdep.h 2009-05-19 15:44:02.000000000 +0200 +@@ -42,9 +42,9 @@ + + #include + +-#ifdef __LITTLE_ENDIAN ++#if defined(__LITTLE_ENDIAN) + #define EFHW_IS_LITTLE_ENDIAN +-#elif __BIG_ENDIAN ++#elif defined(__BIG_ENDIAN) + #define EFHW_IS_BIG_ENDIAN + #else + #error Unknown endianness diff --git a/sfc-external-sram b/sfc-external-sram new file mode 100644 index 0000000..cb8ea0c --- /dev/null +++ b/sfc-external-sram @@ -0,0 +1,298 @@ +From: Kieran Mansley +Subject: enable access to Falcon's external SRAM +References: bnc#489105 + +Include ability to reference external SRAM on Solarflare Falcon NICs to +allow event queues to be accessed by virtualised guests. + +Acked-by: jbeulich@novell.com + +--- head-2009-07-28.orig/drivers/net/sfc/falcon.c 2009-07-28 10:05:40.000000000 +0200 ++++ head-2009-07-28/drivers/net/sfc/falcon.c 2009-07-28 10:06:53.000000000 +0200 +@@ -36,6 +36,9 @@ + + /** + * struct falcon_nic_data - Falcon NIC state ++ * @sram_cfg: SRAM configuration value ++ * @tx_dc_base: Base address in SRAM of TX queue descriptor caches ++ * @rx_dc_base: Base address in SRAM of RX queue descriptor caches + * @next_buffer_table: First available buffer table id + * @resources: Resource information for driverlink client + * @pci_dev2: The secondary PCI device if present +@@ -44,6 +47,9 @@ + * @int_error_expire: Time at which error count will be expired + */ + struct falcon_nic_data { ++ int sram_cfg; ++ unsigned tx_dc_base; ++ unsigned rx_dc_base; + #ifndef CONFIG_SFC_DRIVERLINK + unsigned next_buffer_table; + #else +@@ -74,11 +80,11 @@ static int disable_dma_stats; + */ + #define TX_DC_ENTRIES 16 + #define TX_DC_ENTRIES_ORDER 0 +-#define TX_DC_BASE 0x130000 ++#define TX_DC_INTERNAL_BASE 0x130000 + + #define RX_DC_ENTRIES 64 + #define RX_DC_ENTRIES_ORDER 2 +-#define RX_DC_BASE 0x100000 ++#define RX_DC_INTERNAL_BASE 0x100000 + + static const unsigned int + /* "Large" EEPROM device: Atmel AT25640 or similar +@@ -468,9 +474,17 @@ void falcon_push_buffers(struct efx_tx_q + int falcon_probe_tx(struct efx_tx_queue *tx_queue) + { + struct efx_nic *efx = tx_queue->efx; +- return falcon_alloc_special_buffer(efx, &tx_queue->txd, +- FALCON_TXD_RING_SIZE * +- sizeof(efx_qword_t)); ++ int rc = falcon_alloc_special_buffer(efx, &tx_queue->txd, ++ FALCON_TXD_RING_SIZE * ++ sizeof(efx_qword_t)); ++#ifdef CONFIG_SFC_DRIVERLINK ++ if (rc == 0) { ++ struct falcon_nic_data *nic_data = efx->nic_data; ++ nic_data->resources.txq_min = max(nic_data->resources.txq_min, ++ (unsigned)tx_queue->queue + 1); ++ } ++#endif ++ return rc; + } + + void falcon_init_tx(struct efx_tx_queue *tx_queue) +@@ -610,9 +624,17 @@ void falcon_notify_rx_desc(struct efx_rx + int falcon_probe_rx(struct efx_rx_queue *rx_queue) + { + struct efx_nic *efx = rx_queue->efx; +- return falcon_alloc_special_buffer(efx, &rx_queue->rxd, +- FALCON_RXD_RING_SIZE * +- sizeof(efx_qword_t)); ++ int rc = falcon_alloc_special_buffer(efx, &rx_queue->rxd, ++ FALCON_RXD_RING_SIZE * ++ sizeof(efx_qword_t)); ++#ifdef CONFIG_SFC_DRIVERLINK ++ if (rc == 0) { ++ struct falcon_nic_data *nic_data = efx->nic_data; ++ nic_data->resources.rxq_min = max(nic_data->resources.rxq_min, ++ (unsigned)rx_queue->queue + 1); ++ } ++#endif ++ return rc; + } + + void falcon_init_rx(struct efx_rx_queue *rx_queue) +@@ -1120,9 +1142,18 @@ int falcon_probe_eventq(struct efx_chann + { + struct efx_nic *efx = channel->efx; + unsigned int evq_size; ++ int rc; + + evq_size = FALCON_EVQ_SIZE * sizeof(efx_qword_t); +- return falcon_alloc_special_buffer(efx, &channel->eventq, evq_size); ++ rc = falcon_alloc_special_buffer(efx, &channel->eventq, evq_size); ++#ifdef CONFIG_SFC_DRIVERLINK ++ if (rc == 0) { ++ struct falcon_nic_data *nic_data = efx->nic_data; ++ nic_data->resources.evq_int_min = max(nic_data->resources.evq_int_min, ++ (unsigned)channel->channel + 1); ++ } ++#endif ++ return rc; + } + + void falcon_init_eventq(struct efx_channel *channel) +@@ -2618,19 +2649,22 @@ fail5: + */ + static int falcon_reset_sram(struct efx_nic *efx) + { ++ struct falcon_nic_data *nic_data = efx->nic_data; + efx_oword_t srm_cfg_reg_ker, gpio_cfg_reg_ker; +- int count; ++ int count, onchip, sram_cfg_val; + + /* Set the SRAM wake/sleep GPIO appropriately. */ ++ onchip = (nic_data->sram_cfg == SRM_NB_BSZ_ONCHIP_ONLY); + falcon_read(efx, &gpio_cfg_reg_ker, GPIO_CTL_REG_KER); + EFX_SET_OWORD_FIELD(gpio_cfg_reg_ker, GPIO1_OEN, 1); +- EFX_SET_OWORD_FIELD(gpio_cfg_reg_ker, GPIO1_OUT, 1); ++ EFX_SET_OWORD_FIELD(gpio_cfg_reg_ker, GPIO1_OUT, onchip); + falcon_write(efx, &gpio_cfg_reg_ker, GPIO_CTL_REG_KER); + + /* Initiate SRAM reset */ ++ sram_cfg_val = onchip ? 0 : nic_data->sram_cfg; + EFX_POPULATE_OWORD_2(srm_cfg_reg_ker, + SRAM_OOB_BT_INIT_EN, 1, +- SRM_NUM_BANKS_AND_BANK_SIZE, 0); ++ SRM_NUM_BANKS_AND_BANK_SIZE, sram_cfg_val); + falcon_write(efx, &srm_cfg_reg_ker, SRM_CFG_REG_KER); + + /* Wait for SRAM reset to complete */ +@@ -2702,8 +2736,10 @@ static void falcon_remove_spi_devices(st + /* Extract non-volatile configuration */ + static int falcon_probe_nvconfig(struct efx_nic *efx) + { ++ struct falcon_nic_data *nic_data = efx->nic_data; + struct falcon_nvconfig *nvconfig; + int board_rev; ++ bool onchip_sram; + int rc; + + nvconfig = kmalloc(sizeof(*nvconfig), GFP_KERNEL); +@@ -2716,6 +2752,7 @@ static int falcon_probe_nvconfig(struct + efx->phy_type = PHY_TYPE_NONE; + efx->mdio.prtad = MDIO_PRTAD_NONE; + board_rev = 0; ++ onchip_sram = true; + rc = 0; + } else if (rc) { + goto fail1; +@@ -2726,6 +2763,13 @@ static int falcon_probe_nvconfig(struct + efx->phy_type = v2->port0_phy_type; + efx->mdio.prtad = v2->port0_phy_addr; + board_rev = le16_to_cpu(v2->board_revision); ++#ifdef CONFIG_SFC_DRIVERLINK ++ onchip_sram = EFX_OWORD_FIELD(nvconfig->nic_stat_reg, ++ ONCHIP_SRAM); ++#else ++ /* We have no use for external SRAM */ ++ onchip_sram = true; ++#endif + + if (le16_to_cpu(nvconfig->board_struct_ver) >= 3) { + __le32 fl = v3->spi_device_type[EE_SPI_FLASH]; +@@ -2750,6 +2794,21 @@ static int falcon_probe_nvconfig(struct + + efx_set_board_info(efx, board_rev); + ++ /* Read the SRAM configuration. The register is initialised ++ * automatically but might may been reset since boot. ++ */ ++ if (onchip_sram) { ++ nic_data->sram_cfg = SRM_NB_BSZ_ONCHIP_ONLY; ++ } else { ++ nic_data->sram_cfg = ++ EFX_OWORD_FIELD(nvconfig->srm_cfg_reg, ++ SRM_NUM_BANKS_AND_BANK_SIZE); ++ WARN_ON(nic_data->sram_cfg == SRM_NB_BSZ_RESERVED); ++ /* Replace invalid setting with the smallest defaults */ ++ if (nic_data->sram_cfg == SRM_NB_BSZ_DEFAULT) ++ nic_data->sram_cfg = SRM_NB_BSZ_1BANKS_2M; ++ } ++ + kfree(nvconfig); + return 0; + +@@ -2765,9 +2824,9 @@ static int falcon_probe_nvconfig(struct + * should live. */ + static int falcon_dimension_resources(struct efx_nic *efx) + { ++ struct falcon_nic_data *nic_data = efx->nic_data; + #ifdef CONFIG_SFC_DRIVERLINK + unsigned internal_dcs_entries; +- struct falcon_nic_data *nic_data = efx->nic_data; + struct efx_dl_falcon_resources *res = &nic_data->resources; + + /* Fill out the driverlink resource list */ +@@ -2800,16 +2859,64 @@ static int falcon_dimension_resources(st + break; + } + +- /* Internal SRAM only for now */ +- res->rxq_lim = internal_dcs_entries / RX_DC_ENTRIES; +- res->txq_lim = internal_dcs_entries / TX_DC_ENTRIES; +- res->buffer_table_lim = 8192; ++ if (nic_data->sram_cfg == SRM_NB_BSZ_ONCHIP_ONLY) { ++ res->rxq_lim = internal_dcs_entries / RX_DC_ENTRIES; ++ res->txq_lim = internal_dcs_entries / TX_DC_ENTRIES; ++ res->buffer_table_lim = 8192; ++ nic_data->tx_dc_base = TX_DC_INTERNAL_BASE; ++ nic_data->rx_dc_base = RX_DC_INTERNAL_BASE; ++ } else { ++ unsigned sram_bytes, vnic_bytes, max_vnics, n_vnics, dcs; ++ ++ /* Determine how much SRAM we have to play with. We have ++ * to fit buffer table and descriptor caches in. ++ */ ++ switch (nic_data->sram_cfg) { ++ case SRM_NB_BSZ_1BANKS_2M: ++ default: ++ sram_bytes = 2 * 1024 * 1024; ++ break; ++ case SRM_NB_BSZ_1BANKS_4M: ++ case SRM_NB_BSZ_2BANKS_4M: ++ sram_bytes = 4 * 1024 * 1024; ++ break; ++ case SRM_NB_BSZ_1BANKS_8M: ++ case SRM_NB_BSZ_2BANKS_8M: ++ sram_bytes = 8 * 1024 * 1024; ++ break; ++ case SRM_NB_BSZ_2BANKS_16M: ++ sram_bytes = 16 * 1024 * 1024; ++ break; ++ } ++ /* For each VNIC allow at least 512 buffer table entries ++ * and descriptor cache for an rxq and txq. Buffer table ++ * space for evqs and dmaqs is relatively trivial, so not ++ * considered in this calculation. ++ */ ++ vnic_bytes = 512 * 8 + RX_DC_ENTRIES * 8 + TX_DC_ENTRIES * 8; ++ max_vnics = sram_bytes / vnic_bytes; ++ for (n_vnics = 1; n_vnics < res->evq_timer_min + max_vnics;) ++ n_vnics *= 2; ++ res->rxq_lim = n_vnics; ++ res->txq_lim = n_vnics; ++ ++ dcs = n_vnics * TX_DC_ENTRIES * 8; ++ nic_data->tx_dc_base = sram_bytes - dcs; ++ dcs = n_vnics * RX_DC_ENTRIES * 8; ++ nic_data->rx_dc_base = nic_data->tx_dc_base - dcs; ++ res->buffer_table_lim = nic_data->rx_dc_base / 8; ++ } + + if (FALCON_IS_DUAL_FUNC(efx)) + res->flags |= EFX_DL_FALCON_DUAL_FUNC; + + if (EFX_INT_MODE_USE_MSI(efx)) + res->flags |= EFX_DL_FALCON_USE_MSI; ++#else ++ /* We ignore external SRAM */ ++ EFX_BUG_ON_PARANOID(nic_data->sram_cfg != SRM_NB_BSZ_ONCHIP_ONLY); ++ nic_data->tx_dc_base = TX_DC_INTERNAL_BASE; ++ nic_data->rx_dc_base = RX_DC_INTERNAL_BASE; + #endif + + return 0; +@@ -2998,13 +3105,15 @@ int falcon_probe_nic(struct efx_nic *efx + */ + int falcon_init_nic(struct efx_nic *efx) + { ++ struct falcon_nic_data *nic_data = efx->nic_data; + efx_oword_t temp; + unsigned thresh; + int rc; + +- /* Use on-chip SRAM */ ++ /* Use on-chip SRAM if wanted. */ + falcon_read(efx, &temp, NIC_STAT_REG); +- EFX_SET_OWORD_FIELD(temp, ONCHIP_SRAM, 1); ++ EFX_SET_OWORD_FIELD(temp, ONCHIP_SRAM, ++ nic_data->sram_cfg == SRM_NB_BSZ_ONCHIP_ONLY); + falcon_write(efx, &temp, NIC_STAT_REG); + + /* Set the source of the GMAC clock */ +@@ -3023,9 +3132,9 @@ int falcon_init_nic(struct efx_nic *efx) + return rc; + + /* Set positions of descriptor caches in SRAM. */ +- EFX_POPULATE_OWORD_1(temp, SRM_TX_DC_BASE_ADR, TX_DC_BASE / 8); ++ EFX_POPULATE_OWORD_1(temp, SRM_TX_DC_BASE_ADR, nic_data->tx_dc_base / 8); + falcon_write(efx, &temp, SRM_TX_DC_CFG_REG_KER); +- EFX_POPULATE_OWORD_1(temp, SRM_RX_DC_BASE_ADR, RX_DC_BASE / 8); ++ EFX_POPULATE_OWORD_1(temp, SRM_RX_DC_BASE_ADR, nic_data->rx_dc_base / 8); + falcon_write(efx, &temp, SRM_RX_DC_CFG_REG_KER); + + /* Set TX descriptor cache size. */ diff --git a/sfc-resource-driver b/sfc-resource-driver new file mode 100644 index 0000000..460bb57 --- /dev/null +++ b/sfc-resource-driver @@ -0,0 +1,15052 @@ +From: David Riddoch +# replaces http://xenbits.xensource.com/linux-2.6.18-xen.hg c/s 421: +# HG changeset patch +# User Keir Fraser +# Date 1203330569 0 +# Node ID e4dd072db2595c420bb21d9e835416f4fd543526 +# Parent fc90e9b2c12b316b5460ece28f013e6de881af1a +Subject: Solarflare: Resource driver. +References: FATE#303479 +Acked-by: jbeulich@novell.com + +--- head-2009-04-21.orig/drivers/net/sfc/Kconfig 2009-04-21 11:01:52.000000000 +0200 ++++ head-2009-04-21/drivers/net/sfc/Kconfig 2009-04-21 11:02:22.000000000 +0200 +@@ -11,6 +11,13 @@ config SFC + + To compile this driver as a module, choose M here. The module + will be called sfc. ++ ++config SFC_RESOURCE ++ depends on SFC && X86 ++ tristate "Solarflare Solarstorm SFC4000 resource driver" ++ help ++ This module provides the SFC resource manager driver. ++ + config SFC_MTD + bool "Solarflare Solarstorm SFC4000 flash MTD support" + depends on SFC && MTD && !(SFC=y && MTD=m) +--- head-2009-04-21.orig/drivers/net/sfc/Makefile 2009-04-21 11:01:52.000000000 +0200 ++++ head-2009-04-21/drivers/net/sfc/Makefile 2009-02-06 12:42:18.000000000 +0100 +@@ -5,3 +5,5 @@ sfc-y += efx.o falcon.o tx.o rx.o falc + sfc-$(CONFIG_SFC_MTD) += mtd.o + + obj-$(CONFIG_SFC) += sfc.o ++ ++obj-$(CONFIG_SFC_RESOURCE) += sfc_resource/ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/Makefile 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,14 @@ ++obj-$(CONFIG_SFC_RESOURCE) := sfc_resource.o ++ ++EXTRA_CFLAGS += -D__CI_HARDWARE_CONFIG_FALCON__ ++EXTRA_CFLAGS += -D__ci_driver__ ++EXTRA_CFLAGS += -Werror ++EXTRA_CFLAGS += -Idrivers/net/sfc -Idrivers/net/sfc/sfc_resource ++ ++sfc_resource-objs := resource_driver.o iopage.o efx_vi_shm.o \ ++ driverlink_new.o kernel_proc.o kfifo.o \ ++ nic.o eventq.o falcon.o falcon_hash.o \ ++ assert_valid.o buddy.o buffer_table.o filter_resource.o \ ++ iobufset_resource.o resource_manager.o resources.o \ ++ vi_resource_alloc.o vi_resource_event.o vi_resource_flush.o \ ++ vi_resource_manager.o driver_object.o kernel_compat.o +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/assert_valid.c 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,92 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file contains functions to assert validness of resources and ++ * resource manager in DEBUG build of the resource driver. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * Certain parts of the driver were implemented by ++ * Alexandra Kossovsky ++ * OKTET Labs Ltd, Russia, ++ * http://oktetlabs.ru, ++ * by request of Solarflare Communications ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#include ++ ++#ifndef NDEBUG ++#include ++#include ++#include ++ ++void ++efrm_resource_manager_assert_valid(struct efrm_resource_manager *rm, ++ const char *file, int line) ++{ ++ _EFRM_ASSERT(rm, file, line); ++ _EFRM_ASSERT(rm->rm_name, file, line); ++ _EFRM_ASSERT(rm->rm_type < EFRM_RESOURCE_NUM, file, line); ++ _EFRM_ASSERT(rm->rm_dtor, file, line); ++} ++EXPORT_SYMBOL(efrm_resource_manager_assert_valid); ++ ++/* ++ * \param rs resource to validate ++ * \param ref_count_is_zero One of 3 values ++ * > 0 - check ref count is zero ++ * = 0 - check ref count is non-zero ++ * < 0 - ref count could be any value ++ */ ++void ++efrm_resource_assert_valid(struct efrm_resource *rs, int ref_count_is_zero, ++ const char *file, int line) ++{ ++ struct efrm_resource_manager *rm; ++ ++ _EFRM_ASSERT(rs, file, line); ++ ++ if (ref_count_is_zero >= 0) { ++ if (!(ref_count_is_zero || rs->rs_ref_count > 0) ++ || !(!ref_count_is_zero || rs->rs_ref_count == 0)) ++ EFRM_WARN("%s: check %szero ref=%d " EFRM_RESOURCE_FMT, ++ __func__, ++ ref_count_is_zero == 0 ? "non-" : "", ++ rs->rs_ref_count, ++ EFRM_RESOURCE_PRI_ARG(rs->rs_handle)); ++ ++ _EFRM_ASSERT(!(ref_count_is_zero == 0) || ++ rs->rs_ref_count != 0, file, line); ++ _EFRM_ASSERT(!(ref_count_is_zero > 0) || ++ rs->rs_ref_count == 0, file, line); ++ } ++ ++ rm = efrm_rm_table[EFRM_RESOURCE_TYPE(rs->rs_handle)]; ++ efrm_resource_manager_assert_valid(rm, file, line); ++} ++EXPORT_SYMBOL(efrm_resource_assert_valid); ++ ++#endif +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/buddy.c 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,220 @@ ++ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file contains implementation of a buddy allocator. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * Certain parts of the driver were implemented by ++ * Alexandra Kossovsky ++ * OKTET Labs Ltd, Russia, ++ * http://oktetlabs.ru, ++ * by request of Solarflare Communications ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#include /* get uintXX types on win32 */ ++#include ++#include ++#include ++ ++#if 1 ++#define DEBUG_ALLOC(x) ++#else ++#define DEBUG_ALLOC(x) x ++ ++static inline void efrm_buddy_dump(struct efrm_buddy_allocator *b) ++{ ++ unsigned o; ++ ++ EFRM_NOTICE("%s: dump allocator with order %u", ++ __func__, b->order); ++ for (o = 0; o <= b->order; o++) { ++ struct list_head *l = &b->free_lists[o]; ++ while (l->next != &b->free_lists[o]) { ++ l = l->next; ++ EFRM_NOTICE("%s: order %x: %zx", __func__, o, ++ l - b->links); ++ } ++ } ++} ++#endif ++ ++/* ++ * The purpose of the following inline functions is to give the ++ * understandable names to the simple actions. ++ */ ++static inline void ++efrm_buddy_free_list_add(struct efrm_buddy_allocator *b, ++ unsigned order, unsigned addr) ++{ ++ list_add(&b->links[addr], &b->free_lists[order]); ++ b->orders[addr] = (uint8_t) order; ++} ++static inline void ++efrm_buddy_free_list_del(struct efrm_buddy_allocator *b, unsigned addr) ++{ ++ list_del(&b->links[addr]); ++ b->links[addr].next = NULL; ++} ++static inline int ++efrm_buddy_free_list_empty(struct efrm_buddy_allocator *b, unsigned order) ++{ ++ return list_empty(&b->free_lists[order]); ++} ++static inline unsigned ++efrm_buddy_free_list_pop(struct efrm_buddy_allocator *b, unsigned order) ++{ ++ struct list_head *l = list_pop(&b->free_lists[order]); ++ l->next = NULL; ++ return (unsigned)(l - b->links); ++} ++static inline int ++efrm_buddy_addr_in_free_list(struct efrm_buddy_allocator *b, unsigned addr) ++{ ++ return b->links[addr].next != NULL; ++} ++static inline unsigned ++efrm_buddy_free_list_first(struct efrm_buddy_allocator *b, unsigned order) ++{ ++ return (unsigned)(b->free_lists[order].next - b->links); ++} ++ ++int efrm_buddy_ctor(struct efrm_buddy_allocator *b, unsigned order) ++{ ++ unsigned o; ++ unsigned size = 1 << order; ++ ++ DEBUG_ALLOC(EFRM_NOTICE("%s(%u)", __func__, order)); ++ EFRM_ASSERT(b); ++ EFRM_ASSERT(order <= sizeof(unsigned) * 8 - 1); ++ ++ b->order = order; ++ b->free_lists = vmalloc((order + 1) * sizeof(struct list_head)); ++ if (b->free_lists == NULL) ++ goto fail1; ++ ++ b->links = vmalloc(size * sizeof(struct list_head)); ++ if (b->links == NULL) ++ goto fail2; ++ ++ b->orders = vmalloc(size); ++ if (b->orders == NULL) ++ goto fail3; ++ ++ memset(b->links, 0, size * sizeof(struct list_head)); ++ ++ for (o = 0; o <= b->order; ++o) ++ INIT_LIST_HEAD(b->free_lists + o); ++ ++ efrm_buddy_free_list_add(b, b->order, 0); ++ ++ return 0; ++ ++fail3: ++ vfree(b->links); ++fail2: ++ vfree(b->free_lists); ++fail1: ++ return -ENOMEM; ++} ++ ++void efrm_buddy_dtor(struct efrm_buddy_allocator *b) ++{ ++ EFRM_ASSERT(b); ++ ++ vfree(b->free_lists); ++ vfree(b->links); ++ vfree(b->orders); ++} ++ ++int efrm_buddy_alloc(struct efrm_buddy_allocator *b, unsigned order) ++{ ++ unsigned smallest; ++ unsigned addr; ++ ++ DEBUG_ALLOC(EFRM_NOTICE("%s(%u)", __func__, order)); ++ EFRM_ASSERT(b); ++ ++ /* Find smallest chunk that is big enough. ?? Can optimise this by ++ ** keeping array of pointers to smallest chunk for each order. ++ */ ++ smallest = order; ++ while (smallest <= b->order && ++ efrm_buddy_free_list_empty(b, smallest)) ++ ++smallest; ++ ++ if (smallest > b->order) { ++ DEBUG_ALLOC(EFRM_NOTICE ++ ("buddy - alloc order %d failed - max order %d", ++ order, b->order);); ++ return -ENOMEM; ++ } ++ ++ /* Split blocks until we get one of the correct size. */ ++ addr = efrm_buddy_free_list_pop(b, smallest); ++ ++ DEBUG_ALLOC(EFRM_NOTICE("buddy - alloc %x order %d cut from order %d", ++ addr, order, smallest);); ++ while (smallest-- > order) ++ efrm_buddy_free_list_add(b, smallest, addr + (1 << smallest)); ++ ++ EFRM_DO_DEBUG(b->orders[addr] = (uint8_t) order); ++ ++ EFRM_ASSERT(addr < 1u << b->order); ++ return addr; ++} ++ ++void ++efrm_buddy_free(struct efrm_buddy_allocator *b, unsigned addr, ++ unsigned order) ++{ ++ unsigned buddy_addr; ++ ++ DEBUG_ALLOC(EFRM_NOTICE("%s(%u, %u)", __func__, addr, order)); ++ EFRM_ASSERT(b); ++ EFRM_ASSERT(order <= b->order); ++ EFRM_ASSERT((unsigned long)addr + ((unsigned long)1 << order) <= ++ (unsigned long)1 << b->order); ++ EFRM_ASSERT(!efrm_buddy_addr_in_free_list(b, addr)); ++ EFRM_ASSERT(b->orders[addr] == order); ++ ++ /* merge free blocks */ ++ while (order < b->order) { ++ buddy_addr = addr ^ (1 << order); ++ if (!efrm_buddy_addr_in_free_list(b, buddy_addr) || ++ b->orders[buddy_addr] != order) ++ break; ++ efrm_buddy_free_list_del(b, buddy_addr); ++ if (buddy_addr < addr) ++ addr = buddy_addr; ++ ++order; ++ } ++ ++ DEBUG_ALLOC(EFRM_NOTICE ++ ("buddy - free %x merged into order %d", addr, order);); ++ efrm_buddy_free_list_add(b, order, addr); ++} +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/buffer_table.c 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,209 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file contains abstraction of the buffer table on the NIC. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++/* ++** Might be worth keeping a bitmap of which entries are clear. Then we ++** wouldn't need to clear them all again when we free an allocation. ++*/ ++ ++#include ++#include ++#include ++#include ++#include ++ ++/*! Comment? */ ++struct efrm_buffer_table { ++ spinlock_t lock; ++ struct efrm_buddy_allocator buddy; ++}; ++ ++/* Efab buffer state. */ ++static struct efrm_buffer_table efrm_buffers; ++ ++int efrm_buffer_table_ctor(unsigned low, unsigned high) ++{ ++ int log2_n_entries, rc, i; ++ ++ EFRM_ASSERT(high > 0); ++ EFRM_ASSERT(low < high); ++ ++ EFRM_TRACE("%s: low=%u high=%u", __func__, low, high); ++ EFRM_NOTICE("%s: low=%u high=%u", __func__, low, high); ++ ++ log2_n_entries = fls(high - 1); ++ ++ rc = efrm_buddy_ctor(&efrm_buffers.buddy, log2_n_entries); ++ if (rc < 0) { ++ EFRM_ERR("efrm_buffer_table_ctor: efrm_buddy_ctor(%d) " ++ "failed (%d)", log2_n_entries, rc); ++ return rc; ++ } ++ for (i = 0; i < (1 << log2_n_entries); ++i) { ++ rc = efrm_buddy_alloc(&efrm_buffers.buddy, 0); ++ EFRM_ASSERT(rc >= 0); ++ EFRM_ASSERT(rc < (1 << log2_n_entries)); ++ } ++ for (i = low; i < (int) high; ++i) ++ efrm_buddy_free(&efrm_buffers.buddy, i, 0); ++ ++ spin_lock_init(&efrm_buffers.lock); ++ ++ EFRM_TRACE("%s: done", __func__); ++ ++ return 0; ++} ++ ++void efrm_buffer_table_dtor(void) ++{ ++ /* ?? debug check that all allocations have been freed? */ ++ ++ spin_lock_destroy(&efrm_buffers.lock); ++ efrm_buddy_dtor(&efrm_buffers.buddy); ++ ++ EFRM_TRACE("%s: done", __func__); ++} ++ ++/**********************************************************************/ ++ ++int ++efrm_buffer_table_alloc(unsigned order, ++ struct efhw_buffer_table_allocation *a) ++{ ++ irq_flags_t lock_flags; ++ int rc; ++ ++ EFRM_ASSERT(&efrm_buffers.buddy); ++ EFRM_ASSERT(a); ++ ++ /* Round up to multiple of two, as the buffer clear logic works in ++ * pairs when not in "full" mode. */ ++ order = max_t(unsigned, order, 1); ++ ++ spin_lock_irqsave(&efrm_buffers.lock, lock_flags); ++ rc = efrm_buddy_alloc(&efrm_buffers.buddy, order); ++ spin_unlock_irqrestore(&efrm_buffers.lock, lock_flags); ++ ++ if (rc < 0) { ++ EFRM_ERR("efrm_buffer_table_alloc: failed (n=%ld) rc %d", ++ 1ul << order, rc); ++ return rc; ++ } ++ ++ EFRM_TRACE("efrm_buffer_table_alloc: base=%d n=%ld", ++ rc, 1ul << order); ++ a->order = order; ++ a->base = (unsigned)rc; ++ return 0; ++} ++ ++void efrm_buffer_table_free(struct efhw_buffer_table_allocation *a) ++{ ++ irq_flags_t lock_flags; ++ struct efhw_nic *nic; ++ int nic_i; ++ ++ EFRM_ASSERT(&efrm_buffers.buddy); ++ EFRM_ASSERT(a); ++ EFRM_ASSERT(a->base != -1); ++ EFRM_ASSERT((unsigned long)a->base + (1ul << a->order) <= ++ efrm_buddy_size(&efrm_buffers.buddy)); ++ ++ EFRM_TRACE("efrm_buffer_table_free: base=%d n=%ld", ++ a->base, (1ul << a->order)); ++ ++ EFRM_FOR_EACH_NIC(nic_i, nic) ++ efhw_nic_buffer_table_clear(nic, a->base, 1ul << a->order); ++ ++ spin_lock_irqsave(&efrm_buffers.lock, lock_flags); ++ efrm_buddy_free(&efrm_buffers.buddy, a->base, a->order); ++ spin_unlock_irqrestore(&efrm_buffers.lock, lock_flags); ++ ++ EFRM_DO_DEBUG(a->base = a->order = -1); ++} ++ ++/**********************************************************************/ ++ ++void ++efrm_buffer_table_set(struct efhw_buffer_table_allocation *a, ++ struct efhw_nic *nic, ++ unsigned i, dma_addr_t dma_addr, int owner) ++{ ++ EFRM_ASSERT(a); ++ EFRM_ASSERT(i < (unsigned)1 << a->order); ++ ++ efhw_nic_buffer_table_set(nic, dma_addr, EFHW_NIC_PAGE_SIZE, ++ 0, owner, a->base + i); ++} ++ ++ ++int efrm_buffer_table_size(void) ++{ ++ return efrm_buddy_size(&efrm_buffers.buddy); ++} ++ ++/**********************************************************************/ ++ ++int ++efrm_page_register(struct efhw_nic *nic, dma_addr_t dma_addr, int owner, ++ efhw_buffer_addr_t *buf_addr_out) ++{ ++ struct efhw_buffer_table_allocation alloc; ++ int rc; ++ ++ rc = efrm_buffer_table_alloc(0, &alloc); ++ if (rc == 0) { ++ efrm_buffer_table_set(&alloc, nic, 0, dma_addr, owner); ++ efrm_buffer_table_commit(); ++ *buf_addr_out = EFHW_BUFFER_ADDR(alloc.base, 0); ++ } ++ return rc; ++} ++EXPORT_SYMBOL(efrm_page_register); ++ ++void efrm_page_unregister(efhw_buffer_addr_t buf_addr) ++{ ++ struct efhw_buffer_table_allocation alloc; ++ ++ alloc.order = 0; ++ alloc.base = EFHW_BUFFER_PAGE(buf_addr); ++ efrm_buffer_table_free(&alloc); ++} ++EXPORT_SYMBOL(efrm_page_unregister); ++ ++void efrm_buffer_table_commit(void) ++{ ++ struct efhw_nic *nic; ++ int nic_i; ++ ++ EFRM_FOR_EACH_NIC(nic_i, nic) ++ efhw_nic_buffer_table_commit(nic); ++} +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware.h 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,188 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file provides EtherFabric NIC hardware interface. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * Certain parts of the driver were implemented by ++ * Alexandra Kossovsky ++ * OKTET Labs Ltd, Russia, ++ * http://oktetlabs.ru, ++ * by request of Solarflare Communications ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#ifndef __CI_DRIVER_EFAB_HARDWARE_H__ ++#define __CI_DRIVER_EFAB_HARDWARE_H__ ++ ++#include "ci/driver/efab/hardware/workarounds.h" ++#include ++ ++ ++/*---------------------------------------------------------------------------- ++ * ++ * Common EtherFabric definitions ++ * ++ *---------------------------------------------------------------------------*/ ++ ++#include ++#include ++#include ++ ++/*---------------------------------------------------------------------------- ++ * ++ * EtherFabric varients ++ * ++ *---------------------------------------------------------------------------*/ ++ ++#include ++ ++/*---------------------------------------------------------------------------- ++ * ++ * EtherFabric Portable Hardware Layer defines ++ * ++ *---------------------------------------------------------------------------*/ ++ ++ /*-------------- Initialisation ------------ */ ++#define efhw_nic_close_hardware(nic) \ ++ ((nic)->efhw_func->close_hardware(nic)) ++ ++#define efhw_nic_init_hardware(nic, ev_handlers, mac_addr, non_irq_evq) \ ++ ((nic)->efhw_func->init_hardware((nic), (ev_handlers), (mac_addr), \ ++ (non_irq_evq))) ++ ++/*-------------- Interrupt support ------------ */ ++/** Handle interrupt. Return 0 if not handled, 1 if handled. */ ++#define efhw_nic_interrupt(nic) \ ++ ((nic)->efhw_func->interrupt(nic)) ++ ++#define efhw_nic_interrupt_enable(nic) \ ++ ((nic)->efhw_func->interrupt_enable(nic)) ++ ++#define efhw_nic_interrupt_disable(nic) \ ++ ((nic)->efhw_func->interrupt_disable(nic)) ++ ++#define efhw_nic_set_interrupt_moderation(nic, evq, val) \ ++ ((nic)->efhw_func->set_interrupt_moderation(nic, evq, val)) ++ ++/*-------------- Event support ------------ */ ++ ++#define efhw_nic_event_queue_enable(nic, evq, size, q_base, buf_base, \ ++ interrupting) \ ++ ((nic)->efhw_func->event_queue_enable((nic), (evq), (size), (q_base), \ ++ (buf_base), (interrupting))) ++ ++#define efhw_nic_event_queue_disable(nic, evq, timer_only) \ ++ ((nic)->efhw_func->event_queue_disable(nic, evq, timer_only)) ++ ++#define efhw_nic_wakeup_request(nic, q_base, index, evq) \ ++ ((nic)->efhw_func->wakeup_request(nic, q_base, index, evq)) ++ ++#define efhw_nic_sw_event(nic, data, ev) \ ++ ((nic)->efhw_func->sw_event(nic, data, ev)) ++ ++/*-------------- Filter support ------------ */ ++#define efhw_nic_ipfilter_set(nic, type, index, dmaq, \ ++ saddr, sport, daddr, dport) \ ++ ((nic)->efhw_func->ipfilter_set(nic, type, index, dmaq, \ ++ saddr, sport, daddr, dport)) ++ ++#define efhw_nic_ipfilter_clear(nic, index) \ ++ ((nic)->efhw_func->ipfilter_clear(nic, index)) ++ ++/*-------------- DMA support ------------ */ ++#define efhw_nic_dmaq_tx_q_init(nic, dmaq, evq, owner, tag, \ ++ dmaq_size, index, flags) \ ++ ((nic)->efhw_func->dmaq_tx_q_init(nic, dmaq, evq, owner, tag, \ ++ dmaq_size, index, flags)) ++ ++#define efhw_nic_dmaq_rx_q_init(nic, dmaq, evq, owner, tag, \ ++ dmaq_size, index, flags) \ ++ ((nic)->efhw_func->dmaq_rx_q_init(nic, dmaq, evq, owner, tag, \ ++ dmaq_size, index, flags)) ++ ++#define efhw_nic_dmaq_tx_q_disable(nic, dmaq) \ ++ ((nic)->efhw_func->dmaq_tx_q_disable(nic, dmaq)) ++ ++#define efhw_nic_dmaq_rx_q_disable(nic, dmaq) \ ++ ((nic)->efhw_func->dmaq_rx_q_disable(nic, dmaq)) ++ ++#define efhw_nic_flush_tx_dma_channel(nic, dmaq) \ ++ ((nic)->efhw_func->flush_tx_dma_channel(nic, dmaq)) ++ ++#define efhw_nic_flush_rx_dma_channel(nic, dmaq) \ ++ ((nic)->efhw_func->flush_rx_dma_channel(nic, dmaq)) ++ ++/*-------------- MAC Low level interface ---- */ ++#define efhw_gmac_get_mac_addr(nic) \ ++ ((nic)->gmac->get_mac_addr((nic)->gmac)) ++ ++/*-------------- Buffer table -------------- */ ++#define efhw_nic_buffer_table_set(nic, addr, bufsz, region, \ ++ own_id, buf_id) \ ++ ((nic)->efhw_func->buffer_table_set(nic, addr, bufsz, region, \ ++ own_id, buf_id)) ++ ++#define efhw_nic_buffer_table_set_n(nic, buf_id, addr, bufsz, \ ++ region, n_pages, own_id) \ ++ ((nic)->efhw_func->buffer_table_set_n(nic, buf_id, addr, bufsz, \ ++ region, n_pages, own_id)) ++ ++#define efhw_nic_buffer_table_clear(nic, id, num) \ ++ ((nic)->efhw_func->buffer_table_clear(nic, id, num)) ++ ++#define efhw_nic_buffer_table_commit(nic) \ ++ ((nic)->efhw_func->buffer_table_commit(nic)) ++ ++/*-------------- New filter API ------------ */ ++#define efhw_nic_filter_set(nic, spec, index_out) \ ++ ((nic)->efhw_func->filter_set(nic, spec, index_out)) ++ ++#define efhw_nic_filter_clear(nic, type, index_out) \ ++ ((nic)->efhw_func->filter_clear(nic, type, index_out)) ++ ++ ++/* --- DMA --- */ ++#define EFHW_DMA_ADDRMASK (0xffffffffffffffffULL) ++ ++/* --- Buffers --- */ ++#define EFHW_BUFFER_ADDR FALCON_BUFFER_4K_ADDR ++#define EFHW_BUFFER_PAGE FALCON_BUFFER_4K_PAGE ++#define EFHW_BUFFER_OFF FALCON_BUFFER_4K_OFF ++ ++/* --- Filters --- */ ++#define EFHW_IP_FILTER_NUM FALCON_FILTER_TBL_NUM ++ ++#define EFHW_MAX_PAGE_SIZE FALCON_MAX_PAGE_SIZE ++ ++#if PAGE_SIZE <= EFHW_MAX_PAGE_SIZE ++#define EFHW_NIC_PAGE_SIZE PAGE_SIZE ++#else ++#define EFHW_NIC_PAGE_SIZE EFHW_MAX_PAGE_SIZE ++#endif ++#define EFHW_NIC_PAGE_MASK (~(EFHW_NIC_PAGE_SIZE-1)) ++ ++#endif /* __CI_DRIVER_EFAB_HARDWARE_H__ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/common.h 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,68 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file provides EtherFabric NIC hardware interface common ++ * definitions. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#ifndef __CI_DRIVER_EFAB_HARDWARE_COMMON_H__ ++#define __CI_DRIVER_EFAB_HARDWARE_COMMON_H__ ++ ++/*---------------------------------------------------------------------------- ++ * ++ * EtherFabric constants ++ * ++ *---------------------------------------------------------------------------*/ ++ ++#define EFHW_1K 0x00000400u ++#define EFHW_2K 0x00000800u ++#define EFHW_4K 0x00001000u ++#define EFHW_8K 0x00002000u ++#define EFHW_16K 0x00004000u ++#define EFHW_32K 0x00008000u ++#define EFHW_64K 0x00010000u ++#define EFHW_128K 0x00020000u ++#define EFHW_256K 0x00040000u ++#define EFHW_512K 0x00080000u ++#define EFHW_1M 0x00100000u ++#define EFHW_2M 0x00200000u ++#define EFHW_4M 0x00400000u ++#define EFHW_8M 0x00800000u ++#define EFHW_16M 0x01000000u ++#define EFHW_32M 0x02000000u ++#define EFHW_48M 0x03000000u ++#define EFHW_64M 0x04000000u ++#define EFHW_128M 0x08000000u ++#define EFHW_256M 0x10000000u ++#define EFHW_512M 0x20000000u ++#define EFHW_1G 0x40000000u ++#define EFHW_2G 0x80000000u ++#define EFHW_4G 0x100000000ULL ++#define EFHW_8G 0x200000000ULL ++ ++#endif /* __CI_DRIVER_EFAB_HARDWARE_COMMON_H__ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon.h 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,422 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file provides EtherFabric NIC - EFXXXX (aka Falcon) specific ++ * definitions. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#ifndef __CI_DRIVER_EFAB_HARDWARE_FALCON_H__ ++#define __CI_DRIVER_EFAB_HARDWARE_FALCON_H__ ++ ++/*---------------------------------------------------------------------------- ++ * Compile options ++ *---------------------------------------------------------------------------*/ ++ ++/* Falcon has an 8K maximum page size. */ ++#define FALCON_MAX_PAGE_SIZE EFHW_8K ++ ++/* include the register definitions */ ++#include ++#include ++#include ++#include ++ ++#define FALCON_DMA_TX_DESC_BYTES 8 ++#define FALCON_DMA_RX_PHYS_DESC_BYTES 8 ++#define FALCON_DMA_RX_BUF_DESC_BYTES 4 ++ ++ ++/* ---- efhw_event_t helpers --- */ ++ ++#ifndef EFHW_IS_LITTLE_ENDIAN ++#error This needs lots of cpu_to_le64s() in ++#endif ++ ++/*!\ TODO look at whether there is an efficiency gain to be had by ++ treating the event codes to 32bit masks as is done for EF1 ++ ++ These masks apply to the full 64 bits of the event to extract the ++ event code - followed by the common event codes to expect ++ */ ++#define __FALCON_OPEN_MASK(WIDTH) ((((uint64_t)1) << (WIDTH)) - 1) ++#define FALCON_EVENT_CODE_MASK \ ++ (__FALCON_OPEN_MASK(EV_CODE_WIDTH) << EV_CODE_LBN) ++#define FALCON_EVENT_EV_Q_ID_MASK \ ++ (__FALCON_OPEN_MASK(DRIVER_EV_EVQ_ID_WIDTH) << DRIVER_EV_EVQ_ID_LBN) ++#define FALCON_EVENT_TX_FLUSH_Q_ID_MASK \ ++ (__FALCON_OPEN_MASK(DRIVER_EV_TX_DESCQ_ID_WIDTH) << \ ++ DRIVER_EV_TX_DESCQ_ID_LBN) ++#define FALCON_EVENT_RX_FLUSH_Q_ID_MASK \ ++ (__FALCON_OPEN_MASK(DRIVER_EV_RX_DESCQ_ID_WIDTH) << \ ++ DRIVER_EV_RX_DESCQ_ID_LBN) ++#define FALCON_EVENT_DRV_SUBCODE_MASK \ ++ (__FALCON_OPEN_MASK(DRIVER_EV_SUB_CODE_WIDTH) << \ ++ DRIVER_EV_SUB_CODE_LBN) ++ ++#define FALCON_EVENT_FMT "[ev:%x:%08x:%08x]" ++#define FALCON_EVENT_PRI_ARG(e) \ ++ ((unsigned)(((e).u64 & FALCON_EVENT_CODE_MASK) >> EV_CODE_LBN)), \ ++ ((unsigned)((e).u64 >> 32)), ((unsigned)((e).u64 & 0xFFFFFFFF)) ++ ++#define FALCON_EVENT_CODE(evp) ((evp)->u64 & FALCON_EVENT_CODE_MASK) ++#define FALCON_EVENT_WAKE_EVQ_ID(evp) \ ++ (((evp)->u64 & FALCON_EVENT_EV_Q_ID_MASK) >> DRIVER_EV_EVQ_ID_LBN) ++#define FALCON_EVENT_TX_FLUSH_Q_ID(evp) \ ++ (((evp)->u64 & FALCON_EVENT_TX_FLUSH_Q_ID_MASK) >> \ ++ DRIVER_EV_TX_DESCQ_ID_LBN) ++#define FALCON_EVENT_RX_FLUSH_Q_ID(evp) \ ++ (((evp)->u64 & FALCON_EVENT_RX_FLUSH_Q_ID_MASK) >> \ ++ DRIVER_EV_RX_DESCQ_ID_LBN) ++#define FALCON_EVENT_DRIVER_SUBCODE(evp) \ ++ (((evp)->u64 & FALCON_EVENT_DRV_SUBCODE_MASK) >> \ ++ DRIVER_EV_SUB_CODE_LBN) ++ ++#define FALCON_EVENT_CODE_CHAR ((uint64_t)DRIVER_EV_DECODE << EV_CODE_LBN) ++#define FALCON_EVENT_CODE_SW ((uint64_t)DRV_GEN_EV_DECODE << EV_CODE_LBN) ++ ++ ++/* so this is the size in bytes of an awful lot of things */ ++#define FALCON_REGISTER128 (16) ++ ++/* we define some unique dummy values as a debug aid */ ++#ifdef _WIN32 ++#define FALCON_ATOMIC_BASE 0xdeadbeef00000000ui64 ++#else ++#define FALCON_ATOMIC_BASE 0xdeadbeef00000000ULL ++#endif ++#define FALCON_ATOMIC_UPD_REG (FALCON_ATOMIC_BASE | 0x1) ++#define FALCON_ATOMIC_PTR_TBL_REG (FALCON_ATOMIC_BASE | 0x2) ++#define FALCON_ATOMIC_SRPM_UDP_EVQ_REG (FALCON_ATOMIC_BASE | 0x3) ++#define FALCON_ATOMIC_RX_FLUSH_DESCQ (FALCON_ATOMIC_BASE | 0x4) ++#define FALCON_ATOMIC_TX_FLUSH_DESCQ (FALCON_ATOMIC_BASE | 0x5) ++#define FALCON_ATOMIC_INT_EN_REG (FALCON_ATOMIC_BASE | 0x6) ++#define FALCON_ATOMIC_TIMER_CMD_REG (FALCON_ATOMIC_BASE | 0x7) ++#define FALCON_ATOMIC_PACE_REG (FALCON_ATOMIC_BASE | 0x8) ++#define FALCON_ATOMIC_INT_ACK_REG (FALCON_ATOMIC_BASE | 0x9) ++/* XXX It crashed with odd value in FALCON_ATOMIC_INT_ADR_REG */ ++#define FALCON_ATOMIC_INT_ADR_REG (FALCON_ATOMIC_BASE | 0xa) ++ ++/*---------------------------------------------------------------------------- ++ * ++ * PCI control blocks for Falcon - ++ * (P) primary is for NET ++ * (S) secondary is for CHAR ++ * ++ *---------------------------------------------------------------------------*/ ++ ++#define FALCON_P_CTR_AP_BAR 2 ++#define FALCON_S_CTR_AP_BAR 0 ++#define FALCON_S_DEVID 0x6703 ++ ++ ++/*---------------------------------------------------------------------------- ++ * ++ * Falcon constants ++ * ++ *---------------------------------------------------------------------------*/ ++ ++/* Note: the following constants have moved to values in struct efhw_nic: ++ * FALCON_EVQ_TBL_NUM -> nic->num_evqs ++ * FALCON_DMAQ_NUM -> nic->num_dmaqs ++ * FALCON_TIMERS_NUM -> nic->num_times ++ * These replacement constants are used as sanity checks in assertions in ++ * certain functions that don't have access to struct efhw_nic. ++ */ ++#define FALCON_DMAQ_NUM_SANITY (EFHW_4K) ++#define FALCON_EVQ_TBL_NUM_SANITY (EFHW_4K) ++#define FALCON_TIMERS_NUM_SANITY (EFHW_4K) ++ ++/* This value is an upper limit on the total number of filter table ++ * entries. The actual size of filter table is determined at runtime, as ++ * it can vary. ++ */ ++#define FALCON_FILTER_TBL_NUM (EFHW_8K) ++ ++/* max number of buffers which can be pushed before commiting */ ++#define FALCON_BUFFER_UPD_MAX (128) ++ ++/* We can tell falcon to write its RX buffers in 32 byte quantums, ++ and since we pad packets 2 bytes to the right we can't use ++ a full page (not unless we use jumbo mode for all queues) ++ ++ NOTE: tests/nic/dma.c assumes that the value here is the real NIC ++ value, so we explicitly round it down to the nearest 32 bytes */ ++ ++/* #define FALCON_RX_USR_BUF_SIZE round_down(4096-2,32) */ ++#define FALCON_RX_USR_BUF_SIZE 4064 ++ ++#define FALCON_EVQ_RPTR_REG_P0 0x400 ++ ++/*---------------------------------------------------------------------------- ++ * ++ * Falcon requires user-space descriptor pushes to be: ++ * dword[0-2]; wiob(); dword[3] ++ * ++ * Driver register access must be locked against other threads from ++ * the same driver but can be in any order: i.e dword[0-3]; wiob() ++ * ++ * The following helpers ensure that valid dword orderings are exercised ++ * ++ *---------------------------------------------------------------------------*/ ++ ++/* A union to allow writting 64bit values as 32bit values, without ++ * hitting the compilers aliasing rules. We hope the compiler optimises ++ * away the copy's anyway */ ++union __u64to32 { ++ uint64_t u64; ++ struct { ++#ifdef EFHW_IS_LITTLE_ENDIAN ++ uint32_t a; ++ uint32_t b; ++#else ++ uint32_t b; ++ uint32_t a; ++#endif ++ } s; ++}; ++ ++static inline void ++falcon_write_ddd_d(volatile char __iomem *kva, ++ uint32_t d0, uint32_t d1, uint32_t d2, uint32_t d3) ++{ ++ writel(d0, kva + 0); ++ writel(d1, kva + 4); ++ writel(d2, kva + 8); ++ mmiowb(); ++ writel(d3, kva + 12); ++} ++ ++static inline void falcon_write_q(volatile char __iomem *kva, uint64_t q) ++{ ++ union __u64to32 u; ++ u.u64 = q; ++ ++ writel(u.s.a, kva); ++ mmiowb(); ++ writel(u.s.b, kva + 4); ++} ++ ++static inline void falcon_read_q(volatile char __iomem *addr, uint64_t *q0) ++{ ++ /* It is essential that we read dword0 first, so that ++ * the shadow register is updated with the latest value ++ * and we get a self consistent value. ++ */ ++ union __u64to32 u; ++ u.s.a = readl(addr); ++ rmb(); ++ u.s.b = readl(addr + 4); ++ ++ *q0 = u.u64; ++} ++ ++static inline void ++falcon_write_qq(volatile char __iomem *kva, uint64_t q0, uint64_t q1) ++{ ++ writeq(q0, kva + 0); ++ falcon_write_q(kva + 8, q1); ++} ++ ++static inline void ++falcon_read_qq(volatile char __iomem *addr, uint64_t *q0, uint64_t *q1) ++{ ++ falcon_read_q(addr, q0); ++ *q1 = readq(addr + 8); ++} ++ ++ ++ ++/*---------------------------------------------------------------------------- ++ * ++ * Buffer virtual addresses (4K buffers) ++ * ++ *---------------------------------------------------------------------------*/ ++ ++/* Form a buffer virtual address from buffer ID and offset. If the offset ++** is larger than the buffer size, then the buffer indexed will be ++** calculated appropriately. It is the responsibility of the caller to ++** ensure that they have valid buffers programmed at that address. ++*/ ++#define FALCON_VADDR_8K_S (13) ++#define FALCON_VADDR_4K_S (12) ++#define FALCON_VADDR_M 0xfffff /* post shift mask */ ++ ++#define FALCON_BUFFER_8K_ADDR(id, off) (((id) << FALCON_VADDR_8K_S) + (off)) ++#define FALCON_BUFFER_8K_PAGE(vaddr) \ ++ (((vaddr) >> FALCON_VADDR_8K_S) & FALCON_VADDR_M) ++#define FALCON_BUFFER_8K_OFF(vaddr) \ ++ ((vaddr) & __FALCON_MASK32(FALCON_VADDR_8K_S)) ++ ++#define FALCON_BUFFER_4K_ADDR(id, off) (((id) << FALCON_VADDR_4K_S) + (off)) ++#define FALCON_BUFFER_4K_PAGE(vaddr) \ ++ (((vaddr) >> FALCON_VADDR_4K_S) & FALCON_VADDR_M) ++#define FALCON_BUFFER_4K_OFF(vaddr) \ ++ ((vaddr) & __FALCON_MASK32(FALCON_VADDR_4K_S)) ++ ++/*---------------------------------------------------------------------------- ++ * ++ * Timer helpers ++ * ++ *---------------------------------------------------------------------------*/ ++ ++static inline int falcon_timer_page_addr(uint idx) ++{ ++ ++ EFHW_ASSERT(TIMER_CMD_REG_KER_OFST == ++ (TIMER_CMD_REG_PAGE4_OFST - 4 * EFHW_8K)); ++ ++ EFHW_ASSERT(idx < FALCON_TIMERS_NUM_SANITY); ++ ++ if (idx < 4) ++ return TIMER_CMD_REG_KER_OFST + (idx * EFHW_8K); ++ else if (idx < 1024) ++ return TIMER_CMD_REG_PAGE4_OFST + ((idx - 4) * EFHW_8K); ++ else ++ return TIMER_CMD_REG_PAGE123K_OFST + ((idx - 1024) * EFHW_8K); ++} ++ ++#define FALCON_TIMER_PAGE_MASK (EFHW_8K-1) ++ ++static inline int falcon_timer_page_offset(uint idx) ++{ ++ return falcon_timer_page_addr(idx) & FALCON_TIMER_PAGE_MASK; ++} ++ ++/*---------------------------------------------------------------------------- ++ * ++ * DMA Queue helpers ++ * ++ *---------------------------------------------------------------------------*/ ++ ++/* iSCSI queue for A1; see bug 5427 for more details. */ ++#define FALCON_A1_ISCSI_DMAQ 4 ++ ++/*! returns an address within a bar of the TX DMA doorbell */ ++static inline uint falcon_tx_dma_page_addr(uint dmaq_idx) ++{ ++ uint page; ++ ++ EFHW_ASSERT((((TX_DESC_UPD_REG_PAGE123K_OFST) & (EFHW_8K - 1)) == ++ (((TX_DESC_UPD_REG_PAGE4_OFST) & (EFHW_8K - 1))))); ++ ++ EFHW_ASSERT(dmaq_idx < FALCON_DMAQ_NUM_SANITY); ++ ++ if (dmaq_idx < 1024) ++ page = TX_DESC_UPD_REG_PAGE4_OFST + ((dmaq_idx - 4) * EFHW_8K); ++ else ++ page = ++ TX_DESC_UPD_REG_PAGE123K_OFST + ++ ((dmaq_idx - 1024) * EFHW_8K); ++ ++ return page; ++} ++ ++/*! returns an address within a bar of the RX DMA doorbell */ ++static inline uint falcon_rx_dma_page_addr(uint dmaq_idx) ++{ ++ uint page; ++ ++ EFHW_ASSERT((((RX_DESC_UPD_REG_PAGE123K_OFST) & (EFHW_8K - 1)) == ++ ((RX_DESC_UPD_REG_PAGE4_OFST) & (EFHW_8K - 1)))); ++ ++ EFHW_ASSERT(dmaq_idx < FALCON_DMAQ_NUM_SANITY); ++ ++ if (dmaq_idx < 1024) ++ page = RX_DESC_UPD_REG_PAGE4_OFST + ((dmaq_idx - 4) * EFHW_8K); ++ else ++ page = ++ RX_DESC_UPD_REG_PAGE123K_OFST + ++ ((dmaq_idx - 1024) * EFHW_8K); ++ ++ return page; ++} ++ ++/*! "page"=NIC-dependent register set size */ ++#define FALCON_DMA_PAGE_MASK (EFHW_8K-1) ++ ++/*! returns an address within a bar of the start of the "page" ++ containing the TX DMA doorbell */ ++static inline int falcon_tx_dma_page_base(uint dma_idx) ++{ ++ return falcon_tx_dma_page_addr(dma_idx) & ~FALCON_DMA_PAGE_MASK; ++} ++ ++/*! returns an address within a bar of the start of the "page" ++ containing the RX DMA doorbell */ ++static inline int falcon_rx_dma_page_base(uint dma_idx) ++{ ++ return falcon_rx_dma_page_addr(dma_idx) & ~FALCON_DMA_PAGE_MASK; ++} ++ ++/*! returns an offset within a "page" of the TX DMA doorbell */ ++static inline int falcon_tx_dma_page_offset(uint dma_idx) ++{ ++ return falcon_tx_dma_page_addr(dma_idx) & FALCON_DMA_PAGE_MASK; ++} ++ ++/*! returns an offset within a "page" of the RX DMA doorbell */ ++static inline int falcon_rx_dma_page_offset(uint dma_idx) ++{ ++ return falcon_rx_dma_page_addr(dma_idx) & FALCON_DMA_PAGE_MASK; ++} ++ ++/*---------------------------------------------------------------------------- ++ * ++ * Events ++ * ++ *---------------------------------------------------------------------------*/ ++ ++/* Falcon nails down the event queue mappings */ ++#define FALCON_EVQ_KERNEL0 (0) /* hardwired for net driver */ ++#define FALCON_EVQ_CHAR (4) /* char driver's event queue */ ++ ++/* reserved by the drivers */ ++#define FALCON_EVQ_TBL_RESERVED (8) ++ ++/* default DMA-Q sizes */ ++#define FALCON_DMA_Q_DEFAULT_TX_SIZE 512 ++ ++#define FALCON_DMA_Q_DEFAULT_RX_SIZE 512 ++ ++#define FALCON_DMA_Q_DEFAULT_MMAP \ ++ (FALCON_DMA_Q_DEFAULT_TX_SIZE * (FALCON_DMA_TX_DESC_BYTES * 2)) ++ ++/*---------------------------------------------------------------------------- ++ * ++ * DEBUG - Analyser trigger ++ * ++ *---------------------------------------------------------------------------*/ ++ ++static inline void ++falcon_deadbeef(volatile char __iomem *efhw_kva, unsigned what) ++{ ++ writel(what, efhw_kva + 0x300); ++ mmiowb(); ++} ++#endif /* __CI_DRIVER_EFAB_HARDWARE_FALCON_H__ */ ++/*! \cidoxg_end */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_core.h 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,1147 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file provides EtherFabric NIC - EFXXXX (aka Falcon) core register ++ * definitions. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#define FALCON_EXTENDED_P_BAR 1 ++ ++/*************---- Bus Interface Unit Registers C Header ----*************/ ++#define IOM_IND_ADR_REG_OFST 0x0 /* IO-mapped indirect access address ++ register */ ++ #define IOM_AUTO_ADR_INC_EN_LBN 16 ++ #define IOM_AUTO_ADR_INC_EN_WIDTH 1 ++ #define IOM_IND_ADR_LBN 0 ++ #define IOM_IND_ADR_WIDTH 16 ++#define IOM_IND_DAT_REG_OFST 0x4 /* IO-mapped indirect access data register */ ++ #define IOM_IND_DAT_LBN 0 ++ #define IOM_IND_DAT_WIDTH 32 ++#define ADR_REGION_REG_KER_OFST 0x0 /* Address region register */ ++#define ADR_REGION_REG_OFST 0x0 /* Address region register */ ++ #define ADR_REGION3_LBN 96 ++ #define ADR_REGION3_WIDTH 18 ++ #define ADR_REGION2_LBN 64 ++ #define ADR_REGION2_WIDTH 18 ++ #define ADR_REGION1_LBN 32 ++ #define ADR_REGION1_WIDTH 18 ++ #define ADR_REGION0_LBN 0 ++ #define ADR_REGION0_WIDTH 18 ++#define INT_EN_REG_KER_OFST 0x10 /* Kernel driver Interrupt enable register */ ++ #define KER_INT_CHAR_LBN 4 ++ #define KER_INT_CHAR_WIDTH 1 ++ #define KER_INT_KER_LBN 3 ++ #define KER_INT_KER_WIDTH 1 ++ #define ILL_ADR_ERR_INT_EN_KER_LBN 2 ++ #define ILL_ADR_ERR_INT_EN_KER_WIDTH 1 ++ #define SRM_PERR_INT_EN_KER_LBN 1 ++ #define SRM_PERR_INT_EN_KER_WIDTH 1 ++ #define DRV_INT_EN_KER_LBN 0 ++ #define DRV_INT_EN_KER_WIDTH 1 ++#define INT_EN_REG_CHAR_OFST 0x20 /* Char Driver interrupt enable register */ ++ #define CHAR_INT_CHAR_LBN 4 ++ #define CHAR_INT_CHAR_WIDTH 1 ++ #define CHAR_INT_KER_LBN 3 ++ #define CHAR_INT_KER_WIDTH 1 ++ #define ILL_ADR_ERR_INT_EN_CHAR_LBN 2 ++ #define ILL_ADR_ERR_INT_EN_CHAR_WIDTH 1 ++ #define SRM_PERR_INT_EN_CHAR_LBN 1 ++ #define SRM_PERR_INT_EN_CHAR_WIDTH 1 ++ #define DRV_INT_EN_CHAR_LBN 0 ++ #define DRV_INT_EN_CHAR_WIDTH 1 ++#define INT_ADR_REG_KER_OFST 0x30 /* Interrupt host address for Kernel driver */ ++ #define INT_ADR_KER_LBN 0 ++ #define INT_ADR_KER_WIDTH 64 ++ #define DRV_INT_KER_LBN 32 ++ #define DRV_INT_KER_WIDTH 1 ++ #define EV_FF_HALF_INT_KER_LBN 3 ++ #define EV_FF_HALF_INT_KER_WIDTH 1 ++ #define EV_FF_FULL_INT_KER_LBN 2 ++ #define EV_FF_FULL_INT_KER_WIDTH 1 ++ #define ILL_ADR_ERR_INT_KER_LBN 1 ++ #define ILL_ADR_ERR_INT_KER_WIDTH 1 ++ #define SRAM_PERR_INT_KER_LBN 0 ++ #define SRAM_PERR_INT_KER_WIDTH 1 ++#define INT_ADR_REG_CHAR_OFST 0x40 /* Interrupt host address for Char driver */ ++ #define INT_ADR_CHAR_LBN 0 ++ #define INT_ADR_CHAR_WIDTH 64 ++ #define DRV_INT_CHAR_LBN 32 ++ #define DRV_INT_CHAR_WIDTH 1 ++ #define EV_FF_HALF_INT_CHAR_LBN 3 ++ #define EV_FF_HALF_INT_CHAR_WIDTH 1 ++ #define EV_FF_FULL_INT_CHAR_LBN 2 ++ #define EV_FF_FULL_INT_CHAR_WIDTH 1 ++ #define ILL_ADR_ERR_INT_CHAR_LBN 1 ++ #define ILL_ADR_ERR_INT_CHAR_WIDTH 1 ++ #define SRAM_PERR_INT_CHAR_LBN 0 ++ #define SRAM_PERR_INT_CHAR_WIDTH 1 ++#define INT_ISR0_B0_OFST 0x90 /* B0 only */ ++#define INT_ISR1_B0_OFST 0xA0 ++#define INT_ACK_REG_KER_A1_OFST 0x50 /* Kernel interrupt acknowledge register */ ++ #define RESERVED_LBN 0 ++ #define RESERVED_WIDTH 32 ++#define INT_ACK_REG_CHAR_A1_OFST 0x60 /* CHAR interrupt acknowledge register */ ++ #define RESERVED_LBN 0 ++ #define RESERVED_WIDTH 32 ++/*************---- Global CSR Registers C Header ----*************/ ++#define NIC_STAT_REG_KER_OFST 0x200 /* ASIC strap status register */ ++#define NIC_STAT_REG_OFST 0x200 /* ASIC strap status register */ ++ #define ONCHIP_SRAM_LBN 16 ++ #define ONCHIP_SRAM_WIDTH 0 ++ #define STRAP_PINS_LBN 0 ++ #define STRAP_PINS_WIDTH 3 ++#define GPIO_CTL_REG_KER_OFST 0x210 /* GPIO control register */ ++#define GPIO_CTL_REG_OFST 0x210 /* GPIO control register */ ++ #define GPIO_OEN_LBN 24 ++ #define GPIO_OEN_WIDTH 4 ++ #define GPIO_OUT_LBN 16 ++ #define GPIO_OUT_WIDTH 4 ++ #define GPIO_IN_LBN 8 ++ #define GPIO_IN_WIDTH 4 ++ #define GPIO_PWRUP_VALUE_LBN 0 ++ #define GPIO_PWRUP_VALUE_WIDTH 4 ++#define GLB_CTL_REG_KER_OFST 0x220 /* Global control register */ ++#define GLB_CTL_REG_OFST 0x220 /* Global control register */ ++ #define SWRST_LBN 0 ++ #define SWRST_WIDTH 1 ++#define FATAL_INTR_REG_KER_OFST 0x230 /* Fatal interrupt register for Kernel */ ++ #define PCI_BUSERR_INT_KER_EN_LBN 43 ++ #define PCI_BUSERR_INT_KER_EN_WIDTH 1 ++ #define SRAM_OOB_INT_KER_EN_LBN 42 ++ #define SRAM_OOB_INT_KER_EN_WIDTH 1 ++ #define BUFID_OOB_INT_KER_EN_LBN 41 ++ #define BUFID_OOB_INT_KER_EN_WIDTH 1 ++ #define MEM_PERR_INT_KER_EN_LBN 40 ++ #define MEM_PERR_INT_KER_EN_WIDTH 1 ++ #define RBUF_OWN_INT_KER_EN_LBN 39 ++ #define RBUF_OWN_INT_KER_EN_WIDTH 1 ++ #define TBUF_OWN_INT_KER_EN_LBN 38 ++ #define TBUF_OWN_INT_KER_EN_WIDTH 1 ++ #define RDESCQ_OWN_INT_KER_EN_LBN 37 ++ #define RDESCQ_OWN_INT_KER_EN_WIDTH 1 ++ #define TDESCQ_OWN_INT_KER_EN_LBN 36 ++ #define TDESCQ_OWN_INT_KER_EN_WIDTH 1 ++ #define EVQ_OWN_INT_KER_EN_LBN 35 ++ #define EVQ_OWN_INT_KER_EN_WIDTH 1 ++ #define EVFF_OFLO_INT_KER_EN_LBN 34 ++ #define EVFF_OFLO_INT_KER_EN_WIDTH 1 ++ #define ILL_ADR_INT_KER_EN_LBN 33 ++ #define ILL_ADR_INT_KER_EN_WIDTH 1 ++ #define SRM_PERR_INT_KER_EN_LBN 32 ++ #define SRM_PERR_INT_KER_EN_WIDTH 1 ++ #define PCI_BUSERR_INT_KER_LBN 11 ++ #define PCI_BUSERR_INT_KER_WIDTH 1 ++ #define SRAM_OOB_INT_KER_LBN 10 ++ #define SRAM_OOB_INT_KER_WIDTH 1 ++ #define BUFID_OOB_INT_KER_LBN 9 ++ #define BUFID_OOB_INT_KER_WIDTH 1 ++ #define MEM_PERR_INT_KER_LBN 8 ++ #define MEM_PERR_INT_KER_WIDTH 1 ++ #define RBUF_OWN_INT_KER_LBN 7 ++ #define RBUF_OWN_INT_KER_WIDTH 1 ++ #define TBUF_OWN_INT_KER_LBN 6 ++ #define TBUF_OWN_INT_KER_WIDTH 1 ++ #define RDESCQ_OWN_INT_KER_LBN 5 ++ #define RDESCQ_OWN_INT_KER_WIDTH 1 ++ #define TDESCQ_OWN_INT_KER_LBN 4 ++ #define TDESCQ_OWN_INT_KER_WIDTH 1 ++ #define EVQ_OWN_INT_KER_LBN 3 ++ #define EVQ_OWN_INT_KER_WIDTH 1 ++ #define EVFF_OFLO_INT_KER_LBN 2 ++ #define EVFF_OFLO_INT_KER_WIDTH 1 ++ #define ILL_ADR_INT_KER_LBN 1 ++ #define ILL_ADR_INT_KER_WIDTH 1 ++ #define SRM_PERR_INT_KER_LBN 0 ++ #define SRM_PERR_INT_KER_WIDTH 1 ++#define FATAL_INTR_REG_OFST 0x240 /* Fatal interrupt register for Char */ ++ #define PCI_BUSERR_INT_CHAR_EN_LBN 43 ++ #define PCI_BUSERR_INT_CHAR_EN_WIDTH 1 ++ #define SRAM_OOB_INT_CHAR_EN_LBN 42 ++ #define SRAM_OOB_INT_CHAR_EN_WIDTH 1 ++ #define BUFID_OOB_INT_CHAR_EN_LBN 41 ++ #define BUFID_OOB_INT_CHAR_EN_WIDTH 1 ++ #define MEM_PERR_INT_CHAR_EN_LBN 40 ++ #define MEM_PERR_INT_CHAR_EN_WIDTH 1 ++ #define RBUF_OWN_INT_CHAR_EN_LBN 39 ++ #define RBUF_OWN_INT_CHAR_EN_WIDTH 1 ++ #define TBUF_OWN_INT_CHAR_EN_LBN 38 ++ #define TBUF_OWN_INT_CHAR_EN_WIDTH 1 ++ #define RDESCQ_OWN_INT_CHAR_EN_LBN 37 ++ #define RDESCQ_OWN_INT_CHAR_EN_WIDTH 1 ++ #define TDESCQ_OWN_INT_CHAR_EN_LBN 36 ++ #define TDESCQ_OWN_INT_CHAR_EN_WIDTH 1 ++ #define EVQ_OWN_INT_CHAR_EN_LBN 35 ++ #define EVQ_OWN_INT_CHAR_EN_WIDTH 1 ++ #define EVFF_OFLO_INT_CHAR_EN_LBN 34 ++ #define EVFF_OFLO_INT_CHAR_EN_WIDTH 1 ++ #define ILL_ADR_INT_CHAR_EN_LBN 33 ++ #define ILL_ADR_INT_CHAR_EN_WIDTH 1 ++ #define SRM_PERR_INT_CHAR_EN_LBN 32 ++ #define SRM_PERR_INT_CHAR_EN_WIDTH 1 ++ #define FATAL_INTR_REG_EN_BITS 0xffffffffffffffffULL ++ #define PCI_BUSERR_INT_CHAR_LBN 11 ++ #define PCI_BUSERR_INT_CHAR_WIDTH 1 ++ #define SRAM_OOB_INT_CHAR_LBN 10 ++ #define SRAM_OOB_INT_CHAR_WIDTH 1 ++ #define BUFID_OOB_INT_CHAR_LBN 9 ++ #define BUFID_OOB_INT_CHAR_WIDTH 1 ++ #define MEM_PERR_INT_CHAR_LBN 8 ++ #define MEM_PERR_INT_CHAR_WIDTH 1 ++ #define RBUF_OWN_INT_CHAR_LBN 7 ++ #define RBUF_OWN_INT_CHAR_WIDTH 1 ++ #define TBUF_OWN_INT_CHAR_LBN 6 ++ #define TBUF_OWN_INT_CHAR_WIDTH 1 ++ #define RDESCQ_OWN_INT_CHAR_LBN 5 ++ #define RDESCQ_OWN_INT_CHAR_WIDTH 1 ++ #define TDESCQ_OWN_INT_CHAR_LBN 4 ++ #define TDESCQ_OWN_INT_CHAR_WIDTH 1 ++ #define EVQ_OWN_INT_CHAR_LBN 3 ++ #define EVQ_OWN_INT_CHAR_WIDTH 1 ++ #define EVFF_OFLO_INT_CHAR_LBN 2 ++ #define EVFF_OFLO_INT_CHAR_WIDTH 1 ++ #define ILL_ADR_INT_CHAR_LBN 1 ++ #define ILL_ADR_INT_CHAR_WIDTH 1 ++ #define SRM_PERR_INT_CHAR_LBN 0 ++ #define SRM_PERR_INT_CHAR_WIDTH 1 ++#define DP_CTRL_REG_OFST 0x250 /* Datapath control register */ ++ #define FLS_EVQ_ID_LBN 0 ++ #define FLS_EVQ_ID_WIDTH 12 ++#define MEM_STAT_REG_KER_OFST 0x260 /* Memory status register */ ++#define MEM_STAT_REG_OFST 0x260 /* Memory status register */ ++ #define MEM_PERR_VEC_LBN 53 ++ #define MEM_PERR_VEC_WIDTH 38 ++ #define MBIST_CORR_LBN 38 ++ #define MBIST_CORR_WIDTH 15 ++ #define MBIST_ERR_LBN 0 ++ #define MBIST_ERR_WIDTH 38 ++#define DEBUG_REG_KER_OFST 0x270 /* Debug register */ ++#define DEBUG_REG_OFST 0x270 /* Debug register */ ++ #define DEBUG_BLK_SEL2_LBN 47 ++ #define DEBUG_BLK_SEL2_WIDTH 3 ++ #define DEBUG_BLK_SEL1_LBN 44 ++ #define DEBUG_BLK_SEL1_WIDTH 3 ++ #define DEBUG_BLK_SEL0_LBN 41 ++ #define DEBUG_BLK_SEL0_WIDTH 3 ++ #define MISC_DEBUG_ADDR_LBN 36 ++ #define MISC_DEBUG_ADDR_WIDTH 5 ++ #define SERDES_DEBUG_ADDR_LBN 31 ++ #define SERDES_DEBUG_ADDR_WIDTH 5 ++ #define EM_DEBUG_ADDR_LBN 26 ++ #define EM_DEBUG_ADDR_WIDTH 5 ++ #define SR_DEBUG_ADDR_LBN 21 ++ #define SR_DEBUG_ADDR_WIDTH 5 ++ #define EV_DEBUG_ADDR_LBN 16 ++ #define EV_DEBUG_ADDR_WIDTH 5 ++ #define RX_DEBUG_ADDR_LBN 11 ++ #define RX_DEBUG_ADDR_WIDTH 5 ++ #define TX_DEBUG_ADDR_LBN 6 ++ #define TX_DEBUG_ADDR_WIDTH 5 ++ #define BIU_DEBUG_ADDR_LBN 1 ++ #define BIU_DEBUG_ADDR_WIDTH 5 ++ #define DEBUG_EN_LBN 0 ++ #define DEBUG_EN_WIDTH 1 ++#define DRIVER_REG0_KER_OFST 0x280 /* Driver scratch register 0 */ ++#define DRIVER_REG0_OFST 0x280 /* Driver scratch register 0 */ ++ #define DRIVER_DW0_LBN 0 ++ #define DRIVER_DW0_WIDTH 32 ++#define DRIVER_REG1_KER_OFST 0x290 /* Driver scratch register 1 */ ++#define DRIVER_REG1_OFST 0x290 /* Driver scratch register 1 */ ++ #define DRIVER_DW1_LBN 0 ++ #define DRIVER_DW1_WIDTH 32 ++#define DRIVER_REG2_KER_OFST 0x2A0 /* Driver scratch register 2 */ ++#define DRIVER_REG2_OFST 0x2A0 /* Driver scratch register 2 */ ++ #define DRIVER_DW2_LBN 0 ++ #define DRIVER_DW2_WIDTH 32 ++#define DRIVER_REG3_KER_OFST 0x2B0 /* Driver scratch register 3 */ ++#define DRIVER_REG3_OFST 0x2B0 /* Driver scratch register 3 */ ++ #define DRIVER_DW3_LBN 0 ++ #define DRIVER_DW3_WIDTH 32 ++#define DRIVER_REG4_KER_OFST 0x2C0 /* Driver scratch register 4 */ ++#define DRIVER_REG4_OFST 0x2C0 /* Driver scratch register 4 */ ++ #define DRIVER_DW4_LBN 0 ++ #define DRIVER_DW4_WIDTH 32 ++#define DRIVER_REG5_KER_OFST 0x2D0 /* Driver scratch register 5 */ ++#define DRIVER_REG5_OFST 0x2D0 /* Driver scratch register 5 */ ++ #define DRIVER_DW5_LBN 0 ++ #define DRIVER_DW5_WIDTH 32 ++#define DRIVER_REG6_KER_OFST 0x2E0 /* Driver scratch register 6 */ ++#define DRIVER_REG6_OFST 0x2E0 /* Driver scratch register 6 */ ++ #define DRIVER_DW6_LBN 0 ++ #define DRIVER_DW6_WIDTH 32 ++#define DRIVER_REG7_KER_OFST 0x2F0 /* Driver scratch register 7 */ ++#define DRIVER_REG7_OFST 0x2F0 /* Driver scratch register 7 */ ++ #define DRIVER_DW7_LBN 0 ++ #define DRIVER_DW7_WIDTH 32 ++#define ALTERA_BUILD_REG_OFST 0x300 /* Altera build register */ ++#define ALTERA_BUILD_REG_OFST 0x300 /* Altera build register */ ++ #define ALTERA_BUILD_VER_LBN 0 ++ #define ALTERA_BUILD_VER_WIDTH 32 ++ ++/* so called CSR spare register ++ - contains separate parity enable bits for the various internal memory ++ blocks */ ++#define MEM_PARITY_ERR_EN_REG_KER 0x310 ++#define MEM_PARITY_ALL_BLOCKS_EN_LBN 64 ++#define MEM_PARITY_ALL_BLOCKS_EN_WIDTH 38 ++#define MEM_PARITY_TX_DATA_EN_LBN 72 ++#define MEM_PARITY_TX_DATA_EN_WIDTH 2 ++ ++/*************---- Event & Timer Module Registers C Header ----*************/ ++ ++#if FALCON_EXTENDED_P_BAR ++#define EVQ_RPTR_REG_KER_OFST 0x11B00 /* Event queue read pointer register */ ++#else ++#define EVQ_RPTR_REG_KER_OFST 0x1B00 /* Event queue read pointer register */ ++#endif ++ ++#define EVQ_RPTR_REG_OFST 0xFA0000 /* Event queue read pointer register ++ array. */ ++ #define EVQ_RPTR_LBN 0 ++ #define EVQ_RPTR_WIDTH 15 ++ ++#if FALCON_EXTENDED_P_BAR ++#define EVQ_PTR_TBL_KER_OFST 0x11A00 /* Event queue pointer table for kernel ++ access */ ++#else ++#define EVQ_PTR_TBL_KER_OFST 0x1A00 /* Event queue pointer table for kernel ++ access */ ++#endif ++ ++#define EVQ_PTR_TBL_CHAR_OFST 0xF60000 /* Event queue pointer table for char ++ direct access */ ++ #define EVQ_WKUP_OR_INT_EN_LBN 39 ++ #define EVQ_WKUP_OR_INT_EN_WIDTH 1 ++ #define EVQ_NXT_WPTR_LBN 24 ++ #define EVQ_NXT_WPTR_WIDTH 15 ++ #define EVQ_EN_LBN 23 ++ #define EVQ_EN_WIDTH 1 ++ #define EVQ_SIZE_LBN 20 ++ #define EVQ_SIZE_WIDTH 3 ++ #define EVQ_BUF_BASE_ID_LBN 0 ++ #define EVQ_BUF_BASE_ID_WIDTH 20 ++#define TIMER_CMD_REG_KER_OFST 0x420 /* Timer table for kernel access. ++ Page-mapped */ ++#define TIMER_CMD_REG_PAGE4_OFST 0x8420 /* Timer table for user-level access. ++ Page-mapped. For lowest 1K queues. ++ */ ++#define TIMER_CMD_REG_PAGE123K_OFST 0x1000420 /* Timer table for user-level ++ access. Page-mapped. ++ For upper 3K queues. */ ++#define TIMER_TBL_OFST 0xF70000 /* Timer table for char driver direct access */ ++ #define TIMER_MODE_LBN 12 ++ #define TIMER_MODE_WIDTH 2 ++ #define TIMER_VAL_LBN 0 ++ #define TIMER_VAL_WIDTH 12 ++ #define TIMER_MODE_INT_HLDOFF 2 ++ #define EVQ_BUF_SIZE_LBN 0 ++ #define EVQ_BUF_SIZE_WIDTH 1 ++#define DRV_EV_REG_KER_OFST 0x440 /* Driver generated event register */ ++#define DRV_EV_REG_OFST 0x440 /* Driver generated event register */ ++ #define DRV_EV_QID_LBN 64 ++ #define DRV_EV_QID_WIDTH 12 ++ #define DRV_EV_DATA_LBN 0 ++ #define DRV_EV_DATA_WIDTH 64 ++#define EVQ_CTL_REG_KER_OFST 0x450 /* Event queue control register */ ++#define EVQ_CTL_REG_OFST 0x450 /* Event queue control register */ ++ #define RX_EVQ_WAKEUP_MASK_B0_LBN 15 ++ #define RX_EVQ_WAKEUP_MASK_B0_WIDTH 6 ++ #define EVQ_OWNERR_CTL_LBN 14 ++ #define EVQ_OWNERR_CTL_WIDTH 1 ++ #define EVQ_FIFO_AF_TH_LBN 8 ++ #define EVQ_FIFO_AF_TH_WIDTH 6 ++ #define EVQ_FIFO_NOTAF_TH_LBN 0 ++ #define EVQ_FIFO_NOTAF_TH_WIDTH 6 ++/*************---- SRAM Module Registers C Header ----*************/ ++#define BUF_TBL_CFG_REG_KER_OFST 0x600 /* Buffer table configuration register */ ++#define BUF_TBL_CFG_REG_OFST 0x600 /* Buffer table configuration register */ ++ #define BUF_TBL_MODE_LBN 3 ++ #define BUF_TBL_MODE_WIDTH 1 ++#define SRM_RX_DC_CFG_REG_KER_OFST 0x610 /* SRAM receive descriptor cache ++ configuration register */ ++#define SRM_RX_DC_CFG_REG_OFST 0x610 /* SRAM receive descriptor cache ++ configuration register */ ++ #define SRM_RX_DC_BASE_ADR_LBN 0 ++ #define SRM_RX_DC_BASE_ADR_WIDTH 21 ++#define SRM_TX_DC_CFG_REG_KER_OFST 0x620 /* SRAM transmit descriptor cache ++ configuration register */ ++#define SRM_TX_DC_CFG_REG_OFST 0x620 /* SRAM transmit descriptor cache ++ configuration register */ ++ #define SRM_TX_DC_BASE_ADR_LBN 0 ++ #define SRM_TX_DC_BASE_ADR_WIDTH 21 ++#define SRM_CFG_REG_KER_OFST 0x630 /* SRAM configuration register */ ++#define SRM_CFG_REG_OFST 0x630 /* SRAM configuration register */ ++ #define SRAM_OOB_ADR_INTEN_LBN 5 ++ #define SRAM_OOB_ADR_INTEN_WIDTH 1 ++ #define SRAM_OOB_BUF_INTEN_LBN 4 ++ #define SRAM_OOB_BUF_INTEN_WIDTH 1 ++ #define SRAM_BT_INIT_EN_LBN 3 ++ #define SRAM_BT_INIT_EN_WIDTH 1 ++ #define SRM_NUM_BANK_LBN 2 ++ #define SRM_NUM_BANK_WIDTH 1 ++ #define SRM_BANK_SIZE_LBN 0 ++ #define SRM_BANK_SIZE_WIDTH 2 ++#define BUF_TBL_UPD_REG_KER_OFST 0x650 /* Buffer table update register */ ++#define BUF_TBL_UPD_REG_OFST 0x650 /* Buffer table update register */ ++ #define BUF_UPD_CMD_LBN 63 ++ #define BUF_UPD_CMD_WIDTH 1 ++ #define BUF_CLR_CMD_LBN 62 ++ #define BUF_CLR_CMD_WIDTH 1 ++ #define BUF_CLR_END_ID_LBN 32 ++ #define BUF_CLR_END_ID_WIDTH 20 ++ #define BUF_CLR_START_ID_LBN 0 ++ #define BUF_CLR_START_ID_WIDTH 20 ++#define SRM_UPD_EVQ_REG_KER_OFST 0x660 /* Buffer table update register */ ++#define SRM_UPD_EVQ_REG_OFST 0x660 /* Buffer table update register */ ++ #define SRM_UPD_EVQ_ID_LBN 0 ++ #define SRM_UPD_EVQ_ID_WIDTH 12 ++#define SRAM_PARITY_REG_KER_OFST 0x670 /* SRAM parity register. */ ++#define SRAM_PARITY_REG_OFST 0x670 /* SRAM parity register. */ ++ #define FORCE_SRAM_PERR_LBN 0 ++ #define FORCE_SRAM_PERR_WIDTH 1 ++ ++#if FALCON_EXTENDED_P_BAR ++#define BUF_HALF_TBL_KER_OFST 0x18000 /* Buffer table in half buffer table ++ mode direct access by kernel driver */ ++#else ++#define BUF_HALF_TBL_KER_OFST 0x8000 /* Buffer table in half buffer table ++ mode direct access by kernel driver */ ++#endif ++ ++ ++#define BUF_HALF_TBL_OFST 0x800000 /* Buffer table in half buffer table mode ++ direct access by char driver */ ++ #define BUF_ADR_HBUF_ODD_LBN 44 ++ #define BUF_ADR_HBUF_ODD_WIDTH 20 ++ #define BUF_OWNER_ID_HBUF_ODD_LBN 32 ++ #define BUF_OWNER_ID_HBUF_ODD_WIDTH 12 ++ #define BUF_ADR_HBUF_EVEN_LBN 12 ++ #define BUF_ADR_HBUF_EVEN_WIDTH 20 ++ #define BUF_OWNER_ID_HBUF_EVEN_LBN 0 ++ #define BUF_OWNER_ID_HBUF_EVEN_WIDTH 12 ++ ++ ++#if FALCON_EXTENDED_P_BAR ++#define BUF_FULL_TBL_KER_OFST 0x18000 /* Buffer table in full buffer table ++ mode direct access by kernel driver */ ++#else ++#define BUF_FULL_TBL_KER_OFST 0x8000 /* Buffer table in full buffer table mode ++ direct access by kernel driver */ ++#endif ++ ++ ++ ++ ++#define BUF_FULL_TBL_OFST 0x800000 /* Buffer table in full buffer table mode ++ direct access by char driver */ ++ #define IP_DAT_BUF_SIZE_LBN 50 ++ #define IP_DAT_BUF_SIZE_WIDTH 1 ++ #define BUF_ADR_REGION_LBN 48 ++ #define BUF_ADR_REGION_WIDTH 2 ++ #define BUF_ADR_FBUF_LBN 14 ++ #define BUF_ADR_FBUF_WIDTH 34 ++ #define BUF_OWNER_ID_FBUF_LBN 0 ++ #define BUF_OWNER_ID_FBUF_WIDTH 14 ++#define SRM_DBG_REG_OFST 0x3000000 /* SRAM debug access */ ++ #define SRM_DBG_LBN 0 ++ #define SRM_DBG_WIDTH 64 ++/*************---- RX Datapath Registers C Header ----*************/ ++ ++#define RX_CFG_REG_KER_OFST 0x800 /* Receive configuration register */ ++#define RX_CFG_REG_OFST 0x800 /* Receive configuration register */ ++ ++#if !defined(FALCON_64K_RXFIFO) && !defined(FALCON_PRE_02020029) ++# if !defined(FALCON_128K_RXFIFO) ++# define FALCON_128K_RXFIFO ++# endif ++#endif ++ ++#if defined(FALCON_128K_RXFIFO) ++ ++/* new for B0 */ ++ #define RX_TOEP_TCP_SUPPRESS_B0_LBN 48 ++ #define RX_TOEP_TCP_SUPPRESS_B0_WIDTH 1 ++ #define RX_INGR_EN_B0_LBN 47 ++ #define RX_INGR_EN_B0_WIDTH 1 ++ #define RX_TOEP_IPV4_B0_LBN 46 ++ #define RX_TOEP_IPV4_B0_WIDTH 1 ++ #define RX_HASH_ALG_B0_LBN 45 ++ #define RX_HASH_ALG_B0_WIDTH 1 ++ #define RX_HASH_INSERT_HDR_B0_LBN 44 ++ #define RX_HASH_INSERT_HDR_B0_WIDTH 1 ++/* moved for B0 */ ++ #define RX_DESC_PUSH_EN_B0_LBN 43 ++ #define RX_DESC_PUSH_EN_B0_WIDTH 1 ++ #define RX_RDW_PATCH_EN_LBN 42 /* Non head of line blocking */ ++ #define RX_RDW_PATCH_EN_WIDTH 1 ++ #define RX_PCI_BURST_SIZE_B0_LBN 39 ++ #define RX_PCI_BURST_SIZE_B0_WIDTH 3 ++ #define RX_OWNERR_CTL_B0_LBN 38 ++ #define RX_OWNERR_CTL_B0_WIDTH 1 ++ #define RX_XON_TX_TH_B0_LBN 33 ++ #define RX_XON_TX_TH_B0_WIDTH 5 ++ #define RX_XOFF_TX_TH_B0_LBN 28 ++ #define RX_XOFF_TX_TH_B0_WIDTH 5 ++ #define RX_USR_BUF_SIZE_B0_LBN 19 ++ #define RX_USR_BUF_SIZE_B0_WIDTH 9 ++ #define RX_XON_MAC_TH_B0_LBN 10 ++ #define RX_XON_MAC_TH_B0_WIDTH 9 ++ #define RX_XOFF_MAC_TH_B0_LBN 1 ++ #define RX_XOFF_MAC_TH_B0_WIDTH 9 ++ #define RX_XOFF_MAC_EN_B0_LBN 0 ++ #define RX_XOFF_MAC_EN_B0_WIDTH 1 ++ ++#elif !defined(FALCON_PRE_02020029) ++/* new for B0 */ ++ #define RX_TOEP_TCP_SUPPRESS_B0_LBN 46 ++ #define RX_TOEP_TCP_SUPPRESS_B0_WIDTH 1 ++ #define RX_INGR_EN_B0_LBN 45 ++ #define RX_INGR_EN_B0_WIDTH 1 ++ #define RX_TOEP_IPV4_B0_LBN 44 ++ #define RX_TOEP_IPV4_B0_WIDTH 1 ++ #define RX_HASH_ALG_B0_LBN 43 ++ #define RX_HASH_ALG_B0_WIDTH 41 ++ #define RX_HASH_INSERT_HDR_B0_LBN 42 ++ #define RX_HASH_INSERT_HDR_B0_WIDTH 1 ++/* moved for B0 */ ++ #define RX_DESC_PUSH_EN_B0_LBN 41 ++ #define RX_DESC_PUSH_EN_B0_WIDTH 1 ++ #define RX_PCI_BURST_SIZE_B0_LBN 37 ++ #define RX_PCI_BURST_SIZE_B0_WIDTH 3 ++ #define RX_OWNERR_CTL_B0_LBN 36 ++ #define RX_OWNERR_CTL_B0_WIDTH 1 ++ #define RX_XON_TX_TH_B0_LBN 31 ++ #define RX_XON_TX_TH_B0_WIDTH 5 ++ #define RX_XOFF_TX_TH_B0_LBN 26 ++ #define RX_XOFF_TX_TH_B0_WIDTH 5 ++ #define RX_USR_BUF_SIZE_B0_LBN 17 ++ #define RX_USR_BUF_SIZE_B0_WIDTH 9 ++ #define RX_XON_MAC_TH_B0_LBN 9 ++ #define RX_XON_MAC_TH_B0_WIDTH 8 ++ #define RX_XOFF_MAC_TH_B0_LBN 1 ++ #define RX_XOFF_MAC_TH_B0_WIDTH 8 ++ #define RX_XOFF_MAC_EN_B0_LBN 0 ++ #define RX_XOFF_MAC_EN_B0_WIDTH 1 ++ ++#else ++/* new for B0 */ ++ #define RX_TOEP_TCP_SUPPRESS_B0_LBN 44 ++ #define RX_TOEP_TCP_SUPPRESS_B0_WIDTH 1 ++ #define RX_INGR_EN_B0_LBN 43 ++ #define RX_INGR_EN_B0_WIDTH 1 ++ #define RX_TOEP_IPV4_B0_LBN 42 ++ #define RX_TOEP_IPV4_B0_WIDTH 1 ++ #define RX_HASH_ALG_B0_LBN 41 ++ #define RX_HASH_ALG_B0_WIDTH 41 ++ #define RX_HASH_INSERT_HDR_B0_LBN 40 ++ #define RX_HASH_INSERT_HDR_B0_WIDTH 1 ++/* moved for B0 */ ++ #define RX_DESC_PUSH_EN_B0_LBN 35 ++ #define RX_DESC_PUSH_EN_B0_WIDTH 1 ++ #define RX_PCI_BURST_SIZE_B0_LBN 35 ++ #define RX_PCI_BURST_SIZE_B0_WIDTH 2 ++ #define RX_OWNERR_CTL_B0_LBN 34 ++ #define RX_OWNERR_CTL_B0_WIDTH 1 ++ #define RX_XON_TX_TH_B0_LBN 29 ++ #define RX_XON_TX_TH_B0_WIDTH 5 ++ #define RX_XOFF_TX_TH_B0_LBN 24 ++ #define RX_XOFF_TX_TH_B0_WIDTH 5 ++ #define RX_USR_BUF_SIZE_B0_LBN 15 ++ #define RX_USR_BUF_SIZE_B0_WIDTH 9 ++ #define RX_XON_MAC_TH_B0_LBN 8 ++ #define RX_XON_MAC_TH_B0_WIDTH 7 ++ #define RX_XOFF_MAC_TH_B0_LBN 1 ++ #define RX_XOFF_MAC_TH_B0_WIDTH 7 ++ #define RX_XOFF_MAC_EN_B0_LBN 0 ++ #define RX_XOFF_MAC_EN_B0_WIDTH 1 ++ ++#endif ++ ++/* A0/A1 */ ++ #define RX_PUSH_EN_A1_LBN 35 ++ #define RX_PUSH_EN_A1_WIDTH 1 ++ #define RX_PCI_BURST_SIZE_A1_LBN 31 ++ #define RX_PCI_BURST_SIZE_A1_WIDTH 3 ++ #define RX_OWNERR_CTL_A1_LBN 30 ++ #define RX_OWNERR_CTL_A1_WIDTH 1 ++ #define RX_XON_TX_TH_A1_LBN 25 ++ #define RX_XON_TX_TH_A1_WIDTH 5 ++ #define RX_XOFF_TX_TH_A1_LBN 20 ++ #define RX_XOFF_TX_TH_A1_WIDTH 5 ++ #define RX_USR_BUF_SIZE_A1_LBN 11 ++ #define RX_USR_BUF_SIZE_A1_WIDTH 9 ++ #define RX_XON_MAC_TH_A1_LBN 6 ++ #define RX_XON_MAC_TH_A1_WIDTH 5 ++ #define RX_XOFF_MAC_TH_A1_LBN 1 ++ #define RX_XOFF_MAC_TH_A1_WIDTH 5 ++ #define RX_XOFF_MAC_EN_A1_LBN 0 ++ #define RX_XOFF_MAC_EN_A1_WIDTH 1 ++ ++#define RX_FILTER_CTL_REG_OFST 0x810 /* Receive filter control registers */ ++ #define SCATTER_ENBL_NO_MATCH_Q_B0_LBN 40 ++ #define SCATTER_ENBL_NO_MATCH_Q_B0_WIDTH 1 ++ #define UDP_FULL_SRCH_LIMIT_LBN 32 ++ #define UDP_FULL_SRCH_LIMIT_WIDTH 8 ++ #define NUM_KER_LBN 24 ++ #define NUM_KER_WIDTH 2 ++ #define UDP_WILD_SRCH_LIMIT_LBN 16 ++ #define UDP_WILD_SRCH_LIMIT_WIDTH 8 ++ #define TCP_WILD_SRCH_LIMIT_LBN 8 ++ #define TCP_WILD_SRCH_LIMIT_WIDTH 8 ++ #define TCP_FULL_SRCH_LIMIT_LBN 0 ++ #define TCP_FULL_SRCH_LIMIT_WIDTH 8 ++#define RX_FLUSH_DESCQ_REG_KER_OFST 0x820 /* Receive flush descriptor queue ++ register */ ++#define RX_FLUSH_DESCQ_REG_OFST 0x820 /* Receive flush descriptor queue ++ register */ ++ #define RX_FLUSH_DESCQ_CMD_LBN 24 ++ #define RX_FLUSH_DESCQ_CMD_WIDTH 1 ++ #define RX_FLUSH_EVQ_ID_LBN 12 ++ #define RX_FLUSH_EVQ_ID_WIDTH 12 ++ #define RX_FLUSH_DESCQ_LBN 0 ++ #define RX_FLUSH_DESCQ_WIDTH 12 ++#define RX_DESC_UPD_REG_KER_OFST 0x830 /* Kernel receive descriptor update ++ register. Page-mapped */ ++#define RX_DESC_UPD_REG_PAGE4_OFST 0x8830 /* Char & user receive descriptor ++ update register. Page-mapped. ++ For lowest 1K queues. */ ++#define RX_DESC_UPD_REG_PAGE123K_OFST 0x1000830 /* Char & user receive ++ descriptor update register. ++ Page-mapped. For upper ++ 3K queues. */ ++ #define RX_DESC_WPTR_LBN 96 ++ #define RX_DESC_WPTR_WIDTH 12 ++ #define RX_DESC_PUSH_CMD_LBN 95 ++ #define RX_DESC_PUSH_CMD_WIDTH 1 ++ #define RX_DESC_LBN 0 ++ #define RX_DESC_WIDTH 64 ++ #define RX_KER_DESC_LBN 0 ++ #define RX_KER_DESC_WIDTH 64 ++ #define RX_USR_DESC_LBN 0 ++ #define RX_USR_DESC_WIDTH 32 ++#define RX_DC_CFG_REG_KER_OFST 0x840 /* Receive descriptor cache ++ configuration register */ ++#define RX_DC_CFG_REG_OFST 0x840 /* Receive descriptor cache ++ configuration register */ ++ #define RX_DC_SIZE_LBN 0 ++ #define RX_DC_SIZE_WIDTH 2 ++#define RX_DC_PF_WM_REG_KER_OFST 0x850 /* Receive descriptor cache pre-fetch ++ watermark register */ ++#define RX_DC_PF_WM_REG_OFST 0x850 /* Receive descriptor cache pre-fetch ++ watermark register */ ++ #define RX_DC_PF_LWM_LO_LBN 0 ++ #define RX_DC_PF_LWM_LO_WIDTH 6 ++ ++#define RX_RSS_TKEY_B0_OFST 0x860 /* RSS Toeplitz hash key (B0 only) */ ++ ++#define RX_NODESC_DROP_REG 0x880 ++ #define RX_NODESC_DROP_CNT_LBN 0 ++ #define RX_NODESC_DROP_CNT_WIDTH 16 ++ ++#define XM_TX_CFG_REG_OFST 0x1230 ++ #define XM_AUTO_PAD_LBN 5 ++ #define XM_AUTO_PAD_WIDTH 1 ++ ++#define RX_FILTER_TBL0_OFST 0xF00000 /* Receive filter table - even entries */ ++ #define RSS_EN_0_B0_LBN 110 ++ #define RSS_EN_0_B0_WIDTH 1 ++ #define SCATTER_EN_0_B0_LBN 109 ++ #define SCATTER_EN_0_B0_WIDTH 1 ++ #define TCP_UDP_0_LBN 108 ++ #define TCP_UDP_0_WIDTH 1 ++ #define RXQ_ID_0_LBN 96 ++ #define RXQ_ID_0_WIDTH 12 ++ #define DEST_IP_0_LBN 64 ++ #define DEST_IP_0_WIDTH 32 ++ #define DEST_PORT_TCP_0_LBN 48 ++ #define DEST_PORT_TCP_0_WIDTH 16 ++ #define SRC_IP_0_LBN 16 ++ #define SRC_IP_0_WIDTH 32 ++ #define SRC_TCP_DEST_UDP_0_LBN 0 ++ #define SRC_TCP_DEST_UDP_0_WIDTH 16 ++#define RX_FILTER_TBL1_OFST 0xF00010 /* Receive filter table - odd entries */ ++ #define RSS_EN_1_B0_LBN 110 ++ #define RSS_EN_1_B0_WIDTH 1 ++ #define SCATTER_EN_1_B0_LBN 109 ++ #define SCATTER_EN_1_B0_WIDTH 1 ++ #define TCP_UDP_1_LBN 108 ++ #define TCP_UDP_1_WIDTH 1 ++ #define RXQ_ID_1_LBN 96 ++ #define RXQ_ID_1_WIDTH 12 ++ #define DEST_IP_1_LBN 64 ++ #define DEST_IP_1_WIDTH 32 ++ #define DEST_PORT_TCP_1_LBN 48 ++ #define DEST_PORT_TCP_1_WIDTH 16 ++ #define SRC_IP_1_LBN 16 ++ #define SRC_IP_1_WIDTH 32 ++ #define SRC_TCP_DEST_UDP_1_LBN 0 ++ #define SRC_TCP_DEST_UDP_1_WIDTH 16 ++ ++#if FALCON_EXTENDED_P_BAR ++#define RX_DESC_PTR_TBL_KER_OFST 0x11800 /* Receive descriptor pointer ++ kernel access */ ++#else ++#define RX_DESC_PTR_TBL_KER_OFST 0x1800 /* Receive descriptor pointer ++ kernel access */ ++#endif ++ ++ ++#define RX_DESC_PTR_TBL_OFST 0xF40000 /* Receive descriptor pointer table */ ++ #define RX_ISCSI_DDIG_EN_LBN 88 ++ #define RX_ISCSI_DDIG_EN_WIDTH 1 ++ #define RX_ISCSI_HDIG_EN_LBN 87 ++ #define RX_ISCSI_HDIG_EN_WIDTH 1 ++ #define RX_DESC_PREF_ACT_LBN 86 ++ #define RX_DESC_PREF_ACT_WIDTH 1 ++ #define RX_DC_HW_RPTR_LBN 80 ++ #define RX_DC_HW_RPTR_WIDTH 6 ++ #define RX_DESCQ_HW_RPTR_LBN 68 ++ #define RX_DESCQ_HW_RPTR_WIDTH 12 ++ #define RX_DESCQ_SW_WPTR_LBN 56 ++ #define RX_DESCQ_SW_WPTR_WIDTH 12 ++ #define RX_DESCQ_BUF_BASE_ID_LBN 36 ++ #define RX_DESCQ_BUF_BASE_ID_WIDTH 20 ++ #define RX_DESCQ_EVQ_ID_LBN 24 ++ #define RX_DESCQ_EVQ_ID_WIDTH 12 ++ #define RX_DESCQ_OWNER_ID_LBN 10 ++ #define RX_DESCQ_OWNER_ID_WIDTH 14 ++ #define RX_DESCQ_LABEL_LBN 5 ++ #define RX_DESCQ_LABEL_WIDTH 5 ++ #define RX_DESCQ_SIZE_LBN 3 ++ #define RX_DESCQ_SIZE_WIDTH 2 ++ #define RX_DESCQ_TYPE_LBN 2 ++ #define RX_DESCQ_TYPE_WIDTH 1 ++ #define RX_DESCQ_JUMBO_LBN 1 ++ #define RX_DESCQ_JUMBO_WIDTH 1 ++ #define RX_DESCQ_EN_LBN 0 ++ #define RX_DESCQ_EN_WIDTH 1 ++ ++ ++#define RX_RSS_INDIR_TBL_B0_OFST 0xFB0000 /* RSS indirection table (B0 only) */ ++ #define RX_RSS_INDIR_ENT_B0_LBN 0 ++ #define RX_RSS_INDIR_ENT_B0_WIDTH 6 ++ ++/*************---- TX Datapath Registers C Header ----*************/ ++#define TX_FLUSH_DESCQ_REG_KER_OFST 0xA00 /* Transmit flush descriptor ++ queue register */ ++#define TX_FLUSH_DESCQ_REG_OFST 0xA00 /* Transmit flush descriptor queue ++ register */ ++ #define TX_FLUSH_DESCQ_CMD_LBN 12 ++ #define TX_FLUSH_DESCQ_CMD_WIDTH 1 ++ #define TX_FLUSH_DESCQ_LBN 0 ++ #define TX_FLUSH_DESCQ_WIDTH 12 ++#define TX_DESC_UPD_REG_KER_OFST 0xA10 /* Kernel transmit descriptor update ++ register. Page-mapped */ ++#define TX_DESC_UPD_REG_PAGE4_OFST 0x8A10 /* Char & user transmit descriptor ++ update register. Page-mapped */ ++#define TX_DESC_UPD_REG_PAGE123K_OFST 0x1000A10 /* Char & user transmit ++ descriptor update register. ++ Page-mapped */ ++ #define TX_DESC_WPTR_LBN 96 ++ #define TX_DESC_WPTR_WIDTH 12 ++ #define TX_DESC_PUSH_CMD_LBN 95 ++ #define TX_DESC_PUSH_CMD_WIDTH 1 ++ #define TX_DESC_LBN 0 ++ #define TX_DESC_WIDTH 95 ++ #define TX_KER_DESC_LBN 0 ++ #define TX_KER_DESC_WIDTH 64 ++ #define TX_USR_DESC_LBN 0 ++ #define TX_USR_DESC_WIDTH 64 ++#define TX_DC_CFG_REG_KER_OFST 0xA20 /* Transmit descriptor cache ++ configuration register */ ++#define TX_DC_CFG_REG_OFST 0xA20 /* Transmit descriptor cache configuration ++ register */ ++ #define TX_DC_SIZE_LBN 0 ++ #define TX_DC_SIZE_WIDTH 2 ++ ++#if FALCON_EXTENDED_P_BAR ++#define TX_DESC_PTR_TBL_KER_OFST 0x11900 /* Transmit descriptor pointer. */ ++#else ++#define TX_DESC_PTR_TBL_KER_OFST 0x1900 /* Transmit descriptor pointer. */ ++#endif ++ ++ ++#define TX_DESC_PTR_TBL_OFST 0xF50000 /* Transmit descriptor pointer */ ++ #define TX_NON_IP_DROP_DIS_B0_LBN 91 ++ #define TX_NON_IP_DROP_DIS_B0_WIDTH 1 ++ #define TX_IP_CHKSM_DIS_B0_LBN 90 ++ #define TX_IP_CHKSM_DIS_B0_WIDTH 1 ++ #define TX_TCP_CHKSM_DIS_B0_LBN 89 ++ #define TX_TCP_CHKSM_DIS_B0_WIDTH 1 ++ #define TX_DESCQ_EN_LBN 88 ++ #define TX_DESCQ_EN_WIDTH 1 ++ #define TX_ISCSI_DDIG_EN_LBN 87 ++ #define TX_ISCSI_DDIG_EN_WIDTH 1 ++ #define TX_ISCSI_HDIG_EN_LBN 86 ++ #define TX_ISCSI_HDIG_EN_WIDTH 1 ++ #define TX_DC_HW_RPTR_LBN 80 ++ #define TX_DC_HW_RPTR_WIDTH 6 ++ #define TX_DESCQ_HW_RPTR_LBN 68 ++ #define TX_DESCQ_HW_RPTR_WIDTH 12 ++ #define TX_DESCQ_SW_WPTR_LBN 56 ++ #define TX_DESCQ_SW_WPTR_WIDTH 12 ++ #define TX_DESCQ_BUF_BASE_ID_LBN 36 ++ #define TX_DESCQ_BUF_BASE_ID_WIDTH 20 ++ #define TX_DESCQ_EVQ_ID_LBN 24 ++ #define TX_DESCQ_EVQ_ID_WIDTH 12 ++ #define TX_DESCQ_OWNER_ID_LBN 10 ++ #define TX_DESCQ_OWNER_ID_WIDTH 14 ++ #define TX_DESCQ_LABEL_LBN 5 ++ #define TX_DESCQ_LABEL_WIDTH 5 ++ #define TX_DESCQ_SIZE_LBN 3 ++ #define TX_DESCQ_SIZE_WIDTH 2 ++ #define TX_DESCQ_TYPE_LBN 1 ++ #define TX_DESCQ_TYPE_WIDTH 2 ++ #define TX_DESCQ_FLUSH_LBN 0 ++ #define TX_DESCQ_FLUSH_WIDTH 1 ++#define TX_CFG_REG_KER_OFST 0xA50 /* Transmit configuration register */ ++#define TX_CFG_REG_OFST 0xA50 /* Transmit configuration register */ ++ #define TX_IP_ID_P1_OFS_LBN 32 ++ #define TX_IP_ID_P1_OFS_WIDTH 15 ++ #define TX_IP_ID_P0_OFS_LBN 16 ++ #define TX_IP_ID_P0_OFS_WIDTH 15 ++ #define TX_TURBO_EN_LBN 3 ++ #define TX_TURBO_EN_WIDTH 1 ++ #define TX_OWNERR_CTL_LBN 2 ++ #define TX_OWNERR_CTL_WIDTH 2 ++ #define TX_NON_IP_DROP_DIS_LBN 1 ++ #define TX_NON_IP_DROP_DIS_WIDTH 1 ++ #define TX_IP_ID_REP_EN_LBN 0 ++ #define TX_IP_ID_REP_EN_WIDTH 1 ++#define TX_RESERVED_REG_KER_OFST 0xA80 /* Transmit configuration register */ ++#define TX_RESERVED_REG_OFST 0xA80 /* Transmit configuration register */ ++ #define TX_CSR_PUSH_EN_LBN 89 ++ #define TX_CSR_PUSH_EN_WIDTH 1 ++ #define TX_RX_SPACER_LBN 64 ++ #define TX_RX_SPACER_WIDTH 8 ++ #define TX_SW_EV_EN_LBN 59 ++ #define TX_SW_EV_EN_WIDTH 1 ++ #define TX_RX_SPACER_EN_LBN 57 ++ #define TX_RX_SPACER_EN_WIDTH 1 ++ #define TX_CSR_PREF_WD_TMR_LBN 24 ++ #define TX_CSR_PREF_WD_TMR_WIDTH 16 ++ #define TX_CSR_ONLY1TAG_LBN 21 ++ #define TX_CSR_ONLY1TAG_WIDTH 1 ++ #define TX_PREF_THRESHOLD_LBN 19 ++ #define TX_PREF_THRESHOLD_WIDTH 2 ++ #define TX_ONE_PKT_PER_Q_LBN 18 ++ #define TX_ONE_PKT_PER_Q_WIDTH 1 ++ #define TX_DIS_NON_IP_EV_LBN 17 ++ #define TX_DIS_NON_IP_EV_WIDTH 1 ++ #define TX_DMA_SPACER_LBN 8 ++ #define TX_DMA_SPACER_WIDTH 8 ++ #define TX_FLUSH_MIN_LEN_EN_B0_LBN 7 ++ #define TX_FLUSH_MIN_LEN_EN_B0_WIDTH 1 ++ #define TX_TCP_DIS_A1_LBN 7 ++ #define TX_TCP_DIS_A1_WIDTH 1 ++ #define TX_IP_DIS_A1_LBN 6 ++ #define TX_IP_DIS_A1_WIDTH 1 ++ #define TX_MAX_CPL_LBN 2 ++ #define TX_MAX_CPL_WIDTH 2 ++ #define TX_MAX_PREF_LBN 0 ++ #define TX_MAX_PREF_WIDTH 2 ++#define TX_VLAN_REG_OFST 0xAE0 /* Transmit VLAN tag register */ ++ #define TX_VLAN_EN_LBN 127 ++ #define TX_VLAN_EN_WIDTH 1 ++ #define TX_VLAN7_PORT1_EN_LBN 125 ++ #define TX_VLAN7_PORT1_EN_WIDTH 1 ++ #define TX_VLAN7_PORT0_EN_LBN 124 ++ #define TX_VLAN7_PORT0_EN_WIDTH 1 ++ #define TX_VLAN7_LBN 112 ++ #define TX_VLAN7_WIDTH 12 ++ #define TX_VLAN6_PORT1_EN_LBN 109 ++ #define TX_VLAN6_PORT1_EN_WIDTH 1 ++ #define TX_VLAN6_PORT0_EN_LBN 108 ++ #define TX_VLAN6_PORT0_EN_WIDTH 1 ++ #define TX_VLAN6_LBN 96 ++ #define TX_VLAN6_WIDTH 12 ++ #define TX_VLAN5_PORT1_EN_LBN 93 ++ #define TX_VLAN5_PORT1_EN_WIDTH 1 ++ #define TX_VLAN5_PORT0_EN_LBN 92 ++ #define TX_VLAN5_PORT0_EN_WIDTH 1 ++ #define TX_VLAN5_LBN 80 ++ #define TX_VLAN5_WIDTH 12 ++ #define TX_VLAN4_PORT1_EN_LBN 77 ++ #define TX_VLAN4_PORT1_EN_WIDTH 1 ++ #define TX_VLAN4_PORT0_EN_LBN 76 ++ #define TX_VLAN4_PORT0_EN_WIDTH 1 ++ #define TX_VLAN4_LBN 64 ++ #define TX_VLAN4_WIDTH 12 ++ #define TX_VLAN3_PORT1_EN_LBN 61 ++ #define TX_VLAN3_PORT1_EN_WIDTH 1 ++ #define TX_VLAN3_PORT0_EN_LBN 60 ++ #define TX_VLAN3_PORT0_EN_WIDTH 1 ++ #define TX_VLAN3_LBN 48 ++ #define TX_VLAN3_WIDTH 12 ++ #define TX_VLAN2_PORT1_EN_LBN 45 ++ #define TX_VLAN2_PORT1_EN_WIDTH 1 ++ #define TX_VLAN2_PORT0_EN_LBN 44 ++ #define TX_VLAN2_PORT0_EN_WIDTH 1 ++ #define TX_VLAN2_LBN 32 ++ #define TX_VLAN2_WIDTH 12 ++ #define TX_VLAN1_PORT1_EN_LBN 29 ++ #define TX_VLAN1_PORT1_EN_WIDTH 1 ++ #define TX_VLAN1_PORT0_EN_LBN 28 ++ #define TX_VLAN1_PORT0_EN_WIDTH 1 ++ #define TX_VLAN1_LBN 16 ++ #define TX_VLAN1_WIDTH 12 ++ #define TX_VLAN0_PORT1_EN_LBN 13 ++ #define TX_VLAN0_PORT1_EN_WIDTH 1 ++ #define TX_VLAN0_PORT0_EN_LBN 12 ++ #define TX_VLAN0_PORT0_EN_WIDTH 1 ++ #define TX_VLAN0_LBN 0 ++ #define TX_VLAN0_WIDTH 12 ++#define TX_FIL_CTL_REG_OFST 0xAF0 /* Transmit filter control register */ ++ #define TX_MADR1_FIL_EN_LBN 65 ++ #define TX_MADR1_FIL_EN_WIDTH 1 ++ #define TX_MADR0_FIL_EN_LBN 64 ++ #define TX_MADR0_FIL_EN_WIDTH 1 ++ #define TX_IPFIL31_PORT1_EN_LBN 63 ++ #define TX_IPFIL31_PORT1_EN_WIDTH 1 ++ #define TX_IPFIL31_PORT0_EN_LBN 62 ++ #define TX_IPFIL31_PORT0_EN_WIDTH 1 ++ #define TX_IPFIL30_PORT1_EN_LBN 61 ++ #define TX_IPFIL30_PORT1_EN_WIDTH 1 ++ #define TX_IPFIL30_PORT0_EN_LBN 60 ++ #define TX_IPFIL30_PORT0_EN_WIDTH 1 ++ #define TX_IPFIL29_PORT1_EN_LBN 59 ++ #define TX_IPFIL29_PORT1_EN_WIDTH 1 ++ #define TX_IPFIL29_PORT0_EN_LBN 58 ++ #define TX_IPFIL29_PORT0_EN_WIDTH 1 ++ #define TX_IPFIL28_PORT1_EN_LBN 57 ++ #define TX_IPFIL28_PORT1_EN_WIDTH 1 ++ #define TX_IPFIL28_PORT0_EN_LBN 56 ++ #define TX_IPFIL28_PORT0_EN_WIDTH 1 ++ #define TX_IPFIL27_PORT1_EN_LBN 55 ++ #define TX_IPFIL27_PORT1_EN_WIDTH 1 ++ #define TX_IPFIL27_PORT0_EN_LBN 54 ++ #define TX_IPFIL27_PORT0_EN_WIDTH 1 ++ #define TX_IPFIL26_PORT1_EN_LBN 53 ++ #define TX_IPFIL26_PORT1_EN_WIDTH 1 ++ #define TX_IPFIL26_PORT0_EN_LBN 52 ++ #define TX_IPFIL26_PORT0_EN_WIDTH 1 ++ #define TX_IPFIL25_PORT1_EN_LBN 51 ++ #define TX_IPFIL25_PORT1_EN_WIDTH 1 ++ #define TX_IPFIL25_PORT0_EN_LBN 50 ++ #define TX_IPFIL25_PORT0_EN_WIDTH 1 ++ #define TX_IPFIL24_PORT1_EN_LBN 49 ++ #define TX_IPFIL24_PORT1_EN_WIDTH 1 ++ #define TX_IPFIL24_PORT0_EN_LBN 48 ++ #define TX_IPFIL24_PORT0_EN_WIDTH 1 ++ #define TX_IPFIL23_PORT1_EN_LBN 47 ++ #define TX_IPFIL23_PORT1_EN_WIDTH 1 ++ #define TX_IPFIL23_PORT0_EN_LBN 46 ++ #define TX_IPFIL23_PORT0_EN_WIDTH 1 ++ #define TX_IPFIL22_PORT1_EN_LBN 45 ++ #define TX_IPFIL22_PORT1_EN_WIDTH 1 ++ #define TX_IPFIL22_PORT0_EN_LBN 44 ++ #define TX_IPFIL22_PORT0_EN_WIDTH 1 ++ #define TX_IPFIL21_PORT1_EN_LBN 43 ++ #define TX_IPFIL21_PORT1_EN_WIDTH 1 ++ #define TX_IPFIL21_PORT0_EN_LBN 42 ++ #define TX_IPFIL21_PORT0_EN_WIDTH 1 ++ #define TX_IPFIL20_PORT1_EN_LBN 41 ++ #define TX_IPFIL20_PORT1_EN_WIDTH 1 ++ #define TX_IPFIL20_PORT0_EN_LBN 40 ++ #define TX_IPFIL20_PORT0_EN_WIDTH 1 ++ #define TX_IPFIL19_PORT1_EN_LBN 39 ++ #define TX_IPFIL19_PORT1_EN_WIDTH 1 ++ #define TX_IPFIL19_PORT0_EN_LBN 38 ++ #define TX_IPFIL19_PORT0_EN_WIDTH 1 ++ #define TX_IPFIL18_PORT1_EN_LBN 37 ++ #define TX_IPFIL18_PORT1_EN_WIDTH 1 ++ #define TX_IPFIL18_PORT0_EN_LBN 36 ++ #define TX_IPFIL18_PORT0_EN_WIDTH 1 ++ #define TX_IPFIL17_PORT1_EN_LBN 35 ++ #define TX_IPFIL17_PORT1_EN_WIDTH 1 ++ #define TX_IPFIL17_PORT0_EN_LBN 34 ++ #define TX_IPFIL17_PORT0_EN_WIDTH 1 ++ #define TX_IPFIL16_PORT1_EN_LBN 33 ++ #define TX_IPFIL16_PORT1_EN_WIDTH 1 ++ #define TX_IPFIL16_PORT0_EN_LBN 32 ++ #define TX_IPFIL16_PORT0_EN_WIDTH 1 ++ #define TX_IPFIL15_PORT1_EN_LBN 31 ++ #define TX_IPFIL15_PORT1_EN_WIDTH 1 ++ #define TX_IPFIL15_PORT0_EN_LBN 30 ++ #define TX_IPFIL15_PORT0_EN_WIDTH 1 ++ #define TX_IPFIL14_PORT1_EN_LBN 29 ++ #define TX_IPFIL14_PORT1_EN_WIDTH 1 ++ #define TX_IPFIL14_PORT0_EN_LBN 28 ++ #define TX_IPFIL14_PORT0_EN_WIDTH 1 ++ #define TX_IPFIL13_PORT1_EN_LBN 27 ++ #define TX_IPFIL13_PORT1_EN_WIDTH 1 ++ #define TX_IPFIL13_PORT0_EN_LBN 26 ++ #define TX_IPFIL13_PORT0_EN_WIDTH 1 ++ #define TX_IPFIL12_PORT1_EN_LBN 25 ++ #define TX_IPFIL12_PORT1_EN_WIDTH 1 ++ #define TX_IPFIL12_PORT0_EN_LBN 24 ++ #define TX_IPFIL12_PORT0_EN_WIDTH 1 ++ #define TX_IPFIL11_PORT1_EN_LBN 23 ++ #define TX_IPFIL11_PORT1_EN_WIDTH 1 ++ #define TX_IPFIL11_PORT0_EN_LBN 22 ++ #define TX_IPFIL11_PORT0_EN_WIDTH 1 ++ #define TX_IPFIL10_PORT1_EN_LBN 21 ++ #define TX_IPFIL10_PORT1_EN_WIDTH 1 ++ #define TX_IPFIL10_PORT0_EN_LBN 20 ++ #define TX_IPFIL10_PORT0_EN_WIDTH 1 ++ #define TX_IPFIL9_PORT1_EN_LBN 19 ++ #define TX_IPFIL9_PORT1_EN_WIDTH 1 ++ #define TX_IPFIL9_PORT0_EN_LBN 18 ++ #define TX_IPFIL9_PORT0_EN_WIDTH 1 ++ #define TX_IPFIL8_PORT1_EN_LBN 17 ++ #define TX_IPFIL8_PORT1_EN_WIDTH 1 ++ #define TX_IPFIL8_PORT0_EN_LBN 16 ++ #define TX_IPFIL8_PORT0_EN_WIDTH 1 ++ #define TX_IPFIL7_PORT1_EN_LBN 15 ++ #define TX_IPFIL7_PORT1_EN_WIDTH 1 ++ #define TX_IPFIL7_PORT0_EN_LBN 14 ++ #define TX_IPFIL7_PORT0_EN_WIDTH 1 ++ #define TX_IPFIL6_PORT1_EN_LBN 13 ++ #define TX_IPFIL6_PORT1_EN_WIDTH 1 ++ #define TX_IPFIL6_PORT0_EN_LBN 12 ++ #define TX_IPFIL6_PORT0_EN_WIDTH 1 ++ #define TX_IPFIL5_PORT1_EN_LBN 11 ++ #define TX_IPFIL5_PORT1_EN_WIDTH 1 ++ #define TX_IPFIL5_PORT0_EN_LBN 10 ++ #define TX_IPFIL5_PORT0_EN_WIDTH 1 ++ #define TX_IPFIL4_PORT1_EN_LBN 9 ++ #define TX_IPFIL4_PORT1_EN_WIDTH 1 ++ #define TX_IPFIL4_PORT0_EN_LBN 8 ++ #define TX_IPFIL4_PORT0_EN_WIDTH 1 ++ #define TX_IPFIL3_PORT1_EN_LBN 7 ++ #define TX_IPFIL3_PORT1_EN_WIDTH 1 ++ #define TX_IPFIL3_PORT0_EN_LBN 6 ++ #define TX_IPFIL3_PORT0_EN_WIDTH 1 ++ #define TX_IPFIL2_PORT1_EN_LBN 5 ++ #define TX_IPFIL2_PORT1_EN_WIDTH 1 ++ #define TX_IPFIL2_PORT0_EN_LBN 4 ++ #define TX_IPFIL2_PORT0_EN_WIDTH 1 ++ #define TX_IPFIL1_PORT1_EN_LBN 3 ++ #define TX_IPFIL1_PORT1_EN_WIDTH 1 ++ #define TX_IPFIL1_PORT0_EN_LBN 2 ++ #define TX_IPFIL1_PORT0_EN_WIDTH 1 ++ #define TX_IPFIL0_PORT1_EN_LBN 1 ++ #define TX_IPFIL0_PORT1_EN_WIDTH 1 ++ #define TX_IPFIL0_PORT0_EN_LBN 0 ++ #define TX_IPFIL0_PORT0_EN_WIDTH 1 ++#define TX_IPFIL_TBL_OFST 0xB00 /* Transmit IP source address filter table */ ++ #define TX_IPFIL_MASK_LBN 32 ++ #define TX_IPFIL_MASK_WIDTH 32 ++ #define TX_IP_SRC_ADR_LBN 0 ++ #define TX_IP_SRC_ADR_WIDTH 32 ++#define TX_PACE_REG_A1_OFST 0xF80000 /* Transmit pace control register */ ++#define TX_PACE_REG_B0_OFST 0xA90 /* Transmit pace control register */ ++ #define TX_PACE_SB_NOTAF_LBN 19 ++ #define TX_PACE_SB_NOTAF_WIDTH 10 ++ #define TX_PACE_SB_AF_LBN 9 ++ #define TX_PACE_SB_AF_WIDTH 10 ++ #define TX_PACE_FB_BASE_LBN 5 ++ #define TX_PACE_FB_BASE_WIDTH 4 ++ #define TX_PACE_BIN_TH_LBN 0 ++ #define TX_PACE_BIN_TH_WIDTH 5 ++#define TX_PACE_TBL_A1_OFST 0xF80040 /* Transmit pacing table */ ++#define TX_PACE_TBL_FIRST_QUEUE_A1 4 ++#define TX_PACE_TBL_B0_OFST 0xF80000 /* Transmit pacing table */ ++#define TX_PACE_TBL_FIRST_QUEUE_B0 0 ++ #define TX_PACE_LBN 0 ++ #define TX_PACE_WIDTH 5 ++ ++/*************---- EE/Flash Registers C Header ----*************/ ++#define EE_SPI_HCMD_REG_KER_OFST 0x100 /* SPI host command register */ ++#define EE_SPI_HCMD_REG_OFST 0x100 /* SPI host command register */ ++ #define EE_SPI_HCMD_CMD_EN_LBN 31 ++ #define EE_SPI_HCMD_CMD_EN_WIDTH 1 ++ #define EE_WR_TIMER_ACTIVE_LBN 28 ++ #define EE_WR_TIMER_ACTIVE_WIDTH 1 ++ #define EE_SPI_HCMD_SF_SEL_LBN 24 ++ #define EE_SPI_HCMD_SF_SEL_WIDTH 1 ++ #define EE_SPI_HCMD_DABCNT_LBN 16 ++ #define EE_SPI_HCMD_DABCNT_WIDTH 5 ++ #define EE_SPI_HCMD_READ_LBN 15 ++ #define EE_SPI_HCMD_READ_WIDTH 1 ++ #define EE_SPI_HCMD_DUBCNT_LBN 12 ++ #define EE_SPI_HCMD_DUBCNT_WIDTH 2 ++ #define EE_SPI_HCMD_ADBCNT_LBN 8 ++ #define EE_SPI_HCMD_ADBCNT_WIDTH 2 ++ #define EE_SPI_HCMD_ENC_LBN 0 ++ #define EE_SPI_HCMD_ENC_WIDTH 8 ++#define EE_SPI_HADR_REG_KER_OFST 0X110 /* SPI host address register */ ++#define EE_SPI_HADR_REG_OFST 0X110 /* SPI host address register */ ++ #define EE_SPI_HADR_DUBYTE_LBN 24 ++ #define EE_SPI_HADR_DUBYTE_WIDTH 8 ++ #define EE_SPI_HADR_ADR_LBN 0 ++ #define EE_SPI_HADR_ADR_WIDTH 24 ++#define EE_SPI_HDATA_REG_KER_OFST 0x120 /* SPI host data register */ ++#define EE_SPI_HDATA_REG_OFST 0x120 /* SPI host data register */ ++ #define EE_SPI_HDATA3_LBN 96 ++ #define EE_SPI_HDATA3_WIDTH 32 ++ #define EE_SPI_HDATA2_LBN 64 ++ #define EE_SPI_HDATA2_WIDTH 32 ++ #define EE_SPI_HDATA1_LBN 32 ++ #define EE_SPI_HDATA1_WIDTH 32 ++ #define EE_SPI_HDATA0_LBN 0 ++ #define EE_SPI_HDATA0_WIDTH 32 ++#define EE_BASE_PAGE_REG_KER_OFST 0x130 /* Expansion ROM base mirror register */ ++#define EE_BASE_PAGE_REG_OFST 0x130 /* Expansion ROM base mirror register */ ++ #define EE_EXP_ROM_WINDOW_BASE_LBN 16 ++ #define EE_EXP_ROM_WINDOW_BASE_WIDTH 13 ++ #define EE_EXPROM_MASK_LBN 0 ++ #define EE_EXPROM_MASK_WIDTH 13 ++#define EE_VPD_CFG0_REG_KER_OFST 0X140 /* SPI/VPD configuration register */ ++#define EE_VPD_CFG0_REG_OFST 0X140 /* SPI/VPD configuration register */ ++ #define EE_SF_FASTRD_EN_LBN 127 ++ #define EE_SF_FASTRD_EN_WIDTH 1 ++ #define EE_SF_CLOCK_DIV_LBN 120 ++ #define EE_SF_CLOCK_DIV_WIDTH 7 ++ #define EE_VPD_WIP_POLL_LBN 119 ++ #define EE_VPD_WIP_POLL_WIDTH 1 ++ #define EE_VPDW_LENGTH_LBN 80 ++ #define EE_VPDW_LENGTH_WIDTH 15 ++ #define EE_VPDW_BASE_LBN 64 ++ #define EE_VPDW_BASE_WIDTH 15 ++ #define EE_VPD_WR_CMD_EN_LBN 56 ++ #define EE_VPD_WR_CMD_EN_WIDTH 8 ++ #define EE_VPD_BASE_LBN 32 ++ #define EE_VPD_BASE_WIDTH 24 ++ #define EE_VPD_LENGTH_LBN 16 ++ #define EE_VPD_LENGTH_WIDTH 13 ++ #define EE_VPD_AD_SIZE_LBN 8 ++ #define EE_VPD_AD_SIZE_WIDTH 5 ++ #define EE_VPD_ACCESS_ON_LBN 5 ++ #define EE_VPD_ACCESS_ON_WIDTH 1 ++#define EE_VPD_SW_CNTL_REG_KER_OFST 0X150 /* VPD access SW control register */ ++#define EE_VPD_SW_CNTL_REG_OFST 0X150 /* VPD access SW control register */ ++ #define EE_VPD_CYCLE_PENDING_LBN 31 ++ #define EE_VPD_CYCLE_PENDING_WIDTH 1 ++ #define EE_VPD_CYC_WRITE_LBN 28 ++ #define EE_VPD_CYC_WRITE_WIDTH 1 ++ #define EE_VPD_CYC_ADR_LBN 0 ++ #define EE_VPD_CYC_ADR_WIDTH 15 ++#define EE_VPD_SW_DATA_REG_KER_OFST 0x160 /* VPD access SW data register */ ++#define EE_VPD_SW_DATA_REG_OFST 0x160 /* VPD access SW data register */ ++ #define EE_VPD_CYC_DAT_LBN 0 ++ #define EE_VPD_CYC_DAT_WIDTH 32 +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_desc.h 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,75 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file provides EtherFabric NIC - EFXXXX (aka Falcon) descriptor ++ * definitions. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++/*************---- Descriptors C Headers ----*************/ ++/* Receive Kernel IP Descriptor */ ++ #define RX_KER_BUF_SIZE_LBN 48 ++ #define RX_KER_BUF_SIZE_WIDTH 14 ++ #define RX_KER_BUF_REGION_LBN 46 ++ #define RX_KER_BUF_REGION_WIDTH 2 ++ #define RX_KER_BUF_REGION0_DECODE 0 ++ #define RX_KER_BUF_REGION1_DECODE 1 ++ #define RX_KER_BUF_REGION2_DECODE 2 ++ #define RX_KER_BUF_REGION3_DECODE 3 ++ #define RX_KER_BUF_ADR_LBN 0 ++ #define RX_KER_BUF_ADR_WIDTH 46 ++/* Receive User IP Descriptor */ ++ #define RX_USR_2BYTE_OFS_LBN 20 ++ #define RX_USR_2BYTE_OFS_WIDTH 12 ++ #define RX_USR_BUF_ID_LBN 0 ++ #define RX_USR_BUF_ID_WIDTH 20 ++/* Transmit Kernel IP Descriptor */ ++ #define TX_KER_PORT_LBN 63 ++ #define TX_KER_PORT_WIDTH 1 ++ #define TX_KER_CONT_LBN 62 ++ #define TX_KER_CONT_WIDTH 1 ++ #define TX_KER_BYTE_CNT_LBN 48 ++ #define TX_KER_BYTE_CNT_WIDTH 14 ++ #define TX_KER_BUF_REGION_LBN 46 ++ #define TX_KER_BUF_REGION_WIDTH 2 ++ #define TX_KER_BUF_REGION0_DECODE 0 ++ #define TX_KER_BUF_REGION1_DECODE 1 ++ #define TX_KER_BUF_REGION2_DECODE 2 ++ #define TX_KER_BUF_REGION3_DECODE 3 ++ #define TX_KER_BUF_ADR_LBN 0 ++ #define TX_KER_BUF_ADR_WIDTH 46 ++/* Transmit User IP Descriptor */ ++ #define TX_USR_PORT_LBN 47 ++ #define TX_USR_PORT_WIDTH 1 ++ #define TX_USR_CONT_LBN 46 ++ #define TX_USR_CONT_WIDTH 1 ++ #define TX_USR_BYTE_CNT_LBN 33 ++ #define TX_USR_BYTE_CNT_WIDTH 13 ++ #define TX_USR_BUF_ID_LBN 13 ++ #define TX_USR_BUF_ID_WIDTH 20 ++ #define TX_USR_BYTE_OFS_LBN 0 ++ #define TX_USR_BYTE_OFS_WIDTH 13 +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_event.h 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,155 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file provides EtherFabric NIC - EFXXXX (aka Falcon) event ++ * definitions. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++/*************---- Events Format C Header ----*************/ ++/*************---- Event entry ----*************/ ++ #define EV_CODE_LBN 60 ++ #define EV_CODE_WIDTH 4 ++ #define RX_IP_EV_DECODE 0 ++ #define TX_IP_EV_DECODE 2 ++ #define DRIVER_EV_DECODE 5 ++ #define GLOBAL_EV_DECODE 6 ++ #define DRV_GEN_EV_DECODE 7 ++ #define EV_DATA_LBN 0 ++ #define EV_DATA_WIDTH 60 ++/******---- Receive IP events for both Kernel & User event queues ----******/ ++ #define RX_EV_PKT_OK_LBN 56 ++ #define RX_EV_PKT_OK_WIDTH 1 ++ #define RX_EV_BUF_OWNER_ID_ERR_LBN 54 ++ #define RX_EV_BUF_OWNER_ID_ERR_WIDTH 1 ++ #define RX_EV_IP_HDR_CHKSUM_ERR_LBN 52 ++ #define RX_EV_IP_HDR_CHKSUM_ERR_WIDTH 1 ++ #define RX_EV_TCP_UDP_CHKSUM_ERR_LBN 51 ++ #define RX_EV_TCP_UDP_CHKSUM_ERR_WIDTH 1 ++ #define RX_EV_ETH_CRC_ERR_LBN 50 ++ #define RX_EV_ETH_CRC_ERR_WIDTH 1 ++ #define RX_EV_FRM_TRUNC_LBN 49 ++ #define RX_EV_FRM_TRUNC_WIDTH 1 ++ #define RX_EV_DRIB_NIB_LBN 48 ++ #define RX_EV_DRIB_NIB_WIDTH 1 ++ #define RX_EV_TOBE_DISC_LBN 47 ++ #define RX_EV_TOBE_DISC_WIDTH 1 ++ #define RX_EV_PKT_TYPE_LBN 44 ++ #define RX_EV_PKT_TYPE_WIDTH 3 ++ #define RX_EV_PKT_TYPE_ETH_DECODE 0 ++ #define RX_EV_PKT_TYPE_LLC_DECODE 1 ++ #define RX_EV_PKT_TYPE_JUMBO_DECODE 2 ++ #define RX_EV_PKT_TYPE_VLAN_DECODE 3 ++ #define RX_EV_PKT_TYPE_VLAN_LLC_DECODE 4 ++ #define RX_EV_PKT_TYPE_VLAN_JUMBO_DECODE 5 ++ #define RX_EV_HDR_TYPE_LBN 42 ++ #define RX_EV_HDR_TYPE_WIDTH 2 ++ #define RX_EV_HDR_TYPE_TCP_IPV4_DECODE 0 ++ #define RX_EV_HDR_TYPE_UDP_IPV4_DECODE 1 ++ #define RX_EV_HDR_TYPE_OTHER_IP_DECODE 2 ++ #define RX_EV_HDR_TYPE_NON_IP_DECODE 3 ++ #define RX_EV_DESC_Q_EMPTY_LBN 41 ++ #define RX_EV_DESC_Q_EMPTY_WIDTH 1 ++ #define RX_EV_MCAST_HASH_MATCH_LBN 40 ++ #define RX_EV_MCAST_HASH_MATCH_WIDTH 1 ++ #define RX_EV_MCAST_PKT_LBN 39 ++ #define RX_EV_MCAST_PKT_WIDTH 1 ++ #define RX_EV_Q_LABEL_LBN 32 ++ #define RX_EV_Q_LABEL_WIDTH 5 ++ #define RX_JUMBO_CONT_LBN 31 ++ #define RX_JUMBO_CONT_WIDTH 1 ++ #define RX_SOP_LBN 15 ++ #define RX_SOP_WIDTH 1 ++ #define RX_PORT_LBN 30 ++ #define RX_PORT_WIDTH 1 ++ #define RX_EV_BYTE_CNT_LBN 16 ++ #define RX_EV_BYTE_CNT_WIDTH 14 ++ #define RX_iSCSI_PKT_OK_LBN 14 ++ #define RX_iSCSI_PKT_OK_WIDTH 1 ++ #define RX_ISCSI_DDIG_ERR_LBN 13 ++ #define RX_ISCSI_DDIG_ERR_WIDTH 1 ++ #define RX_ISCSI_HDIG_ERR_LBN 12 ++ #define RX_ISCSI_HDIG_ERR_WIDTH 1 ++ #define RX_EV_DESC_PTR_LBN 0 ++ #define RX_EV_DESC_PTR_WIDTH 12 ++/******---- Transmit IP events for both Kernel & User event queues ----******/ ++ #define TX_EV_PKT_ERR_LBN 38 ++ #define TX_EV_PKT_ERR_WIDTH 1 ++ #define TX_EV_PKT_TOO_BIG_LBN 37 ++ #define TX_EV_PKT_TOO_BIG_WIDTH 1 ++ #define TX_EV_Q_LABEL_LBN 32 ++ #define TX_EV_Q_LABEL_WIDTH 5 ++ #define TX_EV_PORT_LBN 16 ++ #define TX_EV_PORT_WIDTH 1 ++ #define TX_EV_WQ_FF_FULL_LBN 15 ++ #define TX_EV_WQ_FF_FULL_WIDTH 1 ++ #define TX_EV_BUF_OWNER_ID_ERR_LBN 14 ++ #define TX_EV_BUF_OWNER_ID_ERR_WIDTH 1 ++ #define TX_EV_COMP_LBN 12 ++ #define TX_EV_COMP_WIDTH 1 ++ #define TX_EV_DESC_PTR_LBN 0 ++ #define TX_EV_DESC_PTR_WIDTH 12 ++/*************---- Char or Kernel driver events ----*************/ ++ #define DRIVER_EV_SUB_CODE_LBN 56 ++ #define DRIVER_EV_SUB_CODE_WIDTH 4 ++ #define TX_DESCQ_FLS_DONE_EV_DECODE 0x0 ++ #define RX_DESCQ_FLS_DONE_EV_DECODE 0x1 ++ #define EVQ_INIT_DONE_EV_DECODE 0x2 ++ #define EVQ_NOT_EN_EV_DECODE 0x3 ++ #define RX_DESCQ_FLSFF_OVFL_EV_DECODE 0x4 ++ #define SRM_UPD_DONE_EV_DECODE 0x5 ++ #define WAKE_UP_EV_DECODE 0x6 ++ #define TX_PKT_NON_TCP_UDP_DECODE 0x9 ++ #define TIMER_EV_DECODE 0xA ++ #define RX_DSC_ERROR_EV_DECODE 0xE ++ #define DRIVER_EV_TX_DESCQ_ID_LBN 0 ++ #define DRIVER_EV_TX_DESCQ_ID_WIDTH 12 ++ #define DRIVER_EV_RX_DESCQ_ID_LBN 0 ++ #define DRIVER_EV_RX_DESCQ_ID_WIDTH 12 ++ #define DRIVER_EV_EVQ_ID_LBN 0 ++ #define DRIVER_EV_EVQ_ID_WIDTH 12 ++ #define DRIVER_TMR_ID_LBN 0 ++ #define DRIVER_TMR_ID_WIDTH 12 ++ #define DRIVER_EV_SRM_UPD_LBN 0 ++ #define DRIVER_EV_SRM_UPD_WIDTH 2 ++ #define SRM_CLR_EV_DECODE 0 ++ #define SRM_UPD_EV_DECODE 1 ++ #define SRM_ILLCLR_EV_DECODE 2 ++/********---- Global events. Sent to both event queue 0 and 4. ----********/ ++ #define XFP_PHY_INTR_LBN 10 ++ #define XFP_PHY_INTR_WIDTH 1 ++ #define XG_PHY_INTR_LBN 9 ++ #define XG_PHY_INTR_WIDTH 1 ++ #define G_PHY1_INTR_LBN 8 ++ #define G_PHY1_INTR_WIDTH 1 ++ #define G_PHY0_INTR_LBN 7 ++ #define G_PHY0_INTR_WIDTH 1 ++/*************---- Driver generated events ----*************/ ++ #define DRV_GEN_EV_CODE_LBN 60 ++ #define DRV_GEN_EV_CODE_WIDTH 4 ++ #define DRV_GEN_EV_DATA_LBN 0 ++ #define DRV_GEN_EV_DATA_WIDTH 60 +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/falcon/falcon_intr_vec.h 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,44 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file provides EtherFabric NIC - EFXXXX (aka Falcon) interrupt ++ * vector definitions. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++/*************---- Interrupt Vector Format C Header ----*************/ ++#define DW0_OFST 0x0 /* Double-word 0: Event queue FIFO interrupts */ ++ #define EVQ_FIFO_HF_LBN 1 ++ #define EVQ_FIFO_HF_WIDTH 1 ++ #define EVQ_FIFO_AF_LBN 0 ++ #define EVQ_FIFO_AF_WIDTH 1 ++#define DW1_OFST 0x4 /* Double-word 1: Interrupt indicator */ ++ #define INT_FLAG_LBN 0 ++ #define INT_FLAG_WIDTH 1 ++#define DW2_OFST 0x8 /* Double-word 2: Fatal interrupts */ ++ #define FATAL_INT_LBN 0 ++ #define FATAL_INT_WIDTH 1 +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/driver/efab/hardware/workarounds.h 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,67 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file provides workaround settings for EtherFabric NICs. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#ifndef __CI_DRIVER_EFAB_WORKAROUNDS_H__ ++#define __CI_DRIVER_EFAB_WORKAROUNDS_H__ ++ ++/*---------------------------------------------------------------------------- ++ * ++ * Hardware workarounds which have global scope ++ * ++ *---------------------------------------------------------------------------*/ ++ ++#if defined(__CI_HARDWARE_CONFIG_FALCON_B0__) ++/*------------------------------- B0 ---------------------------------------*/ ++ ++#define BUG2175_WORKAROUND 0 /* TX event batching for dual port operation. ++ This removes the effect (dup TX events) ++ of the fix ++ (TX event per packet + batch events) */ ++#define BUG5302_WORKAROUND 0 /* unstick TX DMAQ after out-of-range wr ptr */ ++#define BUG5762_WORKAROUND 0 /* Set all queues to jumbo mode */ ++#define BUG5391_WORKAROUND 0 /* Misaligned TX can't span 512-byte boundary */ ++#define BUG7916_WORKAROUND 0 /* RX flush gets lost */ ++ ++#else ++/*------------------------------- A0/A1 ------------------------------------*/ ++ ++#define BUG2175_WORKAROUND 1 /* TX event batching for dual port operation. ++ This removes the effect (dup TX events) ++ of the fix ++ (TX event per packet + batch events) */ ++#define BUG5302_WORKAROUND 1 /* unstick TX DMAQ after out-of-range wr ptr */ ++#define BUG5762_WORKAROUND 1 /* Set all queues to jumbo mode */ ++#define BUG5391_WORKAROUND 1 /* Misaligned TX can't span 512-byte boundary */ ++#define BUG7916_WORKAROUND 1 /* RX flush gets lost */ ++ ++#endif /* B0/A01 */ ++ ++#endif /* __CI_DRIVER_EFAB_WORKAROUNDS_H__ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/driver/resource/efx_vi.h 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,273 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file contains public EFX VI API to Solarflare resource manager. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#ifndef __CI_DRIVER_RESOURCE_EFX_VI_H__ ++#define __CI_DRIVER_RESOURCE_EFX_VI_H__ ++ ++/* Default size of event queue in the efx_vi resource. Copied from ++ * CI_CFG_NETIF_EVENTQ_SIZE */ ++#define EFX_VI_EVENTQ_SIZE_DEFAULT 1024 ++ ++extern int efx_vi_eventq_size; ++ ++/************************************************************************** ++ * efx_vi_state types, allocation and free ++ **************************************************************************/ ++ ++/*! Handle for refering to a efx_vi */ ++struct efx_vi_state; ++ ++/*! ++ * Allocate an efx_vi, including event queue and pt_endpoint ++ * ++ * \param vih_out Pointer to a handle that is set on success ++ * \param ifindex Index of the network interface desired ++ * \return Zero on success (and vih_out set), non-zero on failure. ++ */ ++extern int ++efx_vi_alloc(struct efx_vi_state **vih_out, int ifindex); ++ ++/*! ++ * Free a previously allocated efx_vi ++ * ++ * \param vih The handle of the efx_vi to free ++ */ ++extern void ++efx_vi_free(struct efx_vi_state *vih); ++ ++/*! ++ * Reset a previously allocated efx_vi ++ * ++ * \param vih The handle of the efx_vi to reset ++ */ ++extern void ++efx_vi_reset(struct efx_vi_state *vih); ++ ++/************************************************************************** ++ * efx_vi_eventq types and functions ++ **************************************************************************/ ++ ++/*! ++ * Register a function to receive callbacks when event queue timeouts ++ * or wakeups occur. Only one function per efx_vi can be registered ++ * at once. ++ * ++ * \param vih The handle to identify the efx_vi ++ * \param callback The function to callback ++ * \param context An argument to pass to the callback function ++ * \return Zero on success, non-zero on failure. ++ */ ++extern int ++efx_vi_eventq_register_callback(struct efx_vi_state *vih, ++ void (*callback)(void *context, int is_timeout), ++ void *context); ++ ++/*! ++ * Remove the current eventq timeout or wakeup callback function ++ * ++ * \param vih The handle to identify the efx_vi ++ * \return Zero on success, non-zero on failure ++ */ ++extern int ++efx_vi_eventq_kill_callback(struct efx_vi_state *vih); ++ ++/************************************************************************** ++ * efx_vi_dma_map types and functions ++ **************************************************************************/ ++ ++/*! ++ * Handle for refering to a efx_vi ++ */ ++struct efx_vi_dma_map_state; ++ ++/*! ++ * Map a list of buffer pages so they are registered with the hardware ++ * ++ * \param vih The handle to identify the efx_vi ++ * \param addrs An array of page pointers to map ++ * \param n_addrs Length of the page pointer array. Must be a power of two. ++ * \param dmh_out Set on success to a handle used to refer to this mapping ++ * \return Zero on success, non-zero on failure. ++ */ ++extern int ++efx_vi_dma_map_pages(struct efx_vi_state *vih, struct page **pages, ++ int n_pages, struct efx_vi_dma_map_state **dmh_out); ++extern int ++efx_vi_dma_map_addrs(struct efx_vi_state *vih, ++ unsigned long long *dev_bus_addrs, int n_pages, ++ struct efx_vi_dma_map_state **dmh_out); ++ ++/*! ++ * Unmap a previously mapped set of pages so they are no longer registered ++ * with the hardware. ++ * ++ * \param vih The handle to identify the efx_vi ++ * \param dmh The handle to identify the dma mapping ++ */ ++extern void ++efx_vi_dma_unmap_pages(struct efx_vi_state *vih, ++ struct efx_vi_dma_map_state *dmh); ++extern void ++efx_vi_dma_unmap_addrs(struct efx_vi_state *vih, ++ struct efx_vi_dma_map_state *dmh); ++ ++/*! ++ * Retrieve the buffer address of the mapping ++ * ++ * \param vih The handle to identify the efx_vi ++ * \param dmh The handle to identify the buffer mapping ++ * \return The buffer address on success, or zero on failure ++ */ ++extern unsigned ++efx_vi_dma_get_map_addr(struct efx_vi_state *vih, ++ struct efx_vi_dma_map_state *dmh); ++ ++/************************************************************************** ++ * efx_vi filter functions ++ **************************************************************************/ ++ ++#define EFX_VI_STATIC_FILTERS 32 ++ ++/*! Handle to refer to a filter instance */ ++struct filter_resource_t; ++ ++/*! ++ * Allocate and add a filter ++ * ++ * \param vih The handle to identify the efx_vi ++ * \param protocol The protocol of the new filter: UDP or TCP ++ * \param ip_addr_be32 The local ip address of the filter ++ * \param port_le16 The local port of the filter ++ * \param fh_out Set on success to be a handle to refer to this filter ++ * \return Zero on success, non-zero on failure. ++ */ ++extern int ++efx_vi_filter(struct efx_vi_state *vih, int protocol, unsigned ip_addr_be32, ++ int port_le16, struct filter_resource_t **fh_out); ++ ++/*! ++ * Remove a filter and free resources associated with it ++ * ++ * \param vih The handle to identify the efx_vi ++ * \param fh The handle to identify the filter ++ * \return Zero on success, non-zero on failure ++ */ ++extern int ++efx_vi_filter_stop(struct efx_vi_state *vih, struct filter_resource_t *fh); ++ ++/************************************************************************** ++ * efx_vi hw resources types and functions ++ **************************************************************************/ ++ ++/*! Constants for the type field in efx_vi_hw_resource */ ++#define EFX_VI_HW_RESOURCE_TXDMAQ 0x0 /* PFN of TX DMA Q */ ++#define EFX_VI_HW_RESOURCE_RXDMAQ 0x1 /* PFN of RX DMA Q */ ++#define EFX_VI_HW_RESOURCE_EVQTIMER 0x4 /* Address of event q timer */ ++ ++/* Address of event q pointer (EF1) */ ++#define EFX_VI_HW_RESOURCE_EVQPTR 0x5 ++/* Address of register pointer (Falcon A) */ ++#define EFX_VI_HW_RESOURCE_EVQRPTR 0x6 ++/* Offset of register pointer (Falcon B) */ ++#define EFX_VI_HW_RESOURCE_EVQRPTR_OFFSET 0x7 ++/* Address of mem KVA */ ++#define EFX_VI_HW_RESOURCE_EVQMEMKVA 0x8 ++/* PFN of doorbell page (Falcon) */ ++#define EFX_VI_HW_RESOURCE_BELLPAGE 0x9 ++ ++/*! How large an array to allocate for the get_() functions - smaller ++ than the total number of constants as some are mutually exclusive */ ++#define EFX_VI_HW_RESOURCE_MAXSIZE 0x7 ++ ++/*! Constants for the mem_type field in efx_vi_hw_resource */ ++#define EFX_VI_HW_RESOURCE_IOBUFFER 0 /* Host memory */ ++#define EFX_VI_HW_RESOURCE_PERIPHERAL 1 /* Card memory/registers */ ++ ++/*! ++ * Data structure providing information on a hardware resource mapping ++ */ ++struct efx_vi_hw_resource { ++ u8 type; /*!< What this resource represents */ ++ u8 mem_type; /*!< What type of memory is it in, eg, ++ * host or iomem */ ++ u8 more_to_follow; /*!< Is this part of a multi-region resource */ ++ u32 length; /*!< Length of the resource in bytes */ ++ unsigned long address; /*!< Address of this resource */ ++}; ++ ++/*! ++ * Metadata concerning the list of hardware resource mappings ++ */ ++struct efx_vi_hw_resource_metadata { ++ int evq_order; ++ int evq_offs; ++ int evq_capacity; ++ int instance; ++ unsigned rx_capacity; ++ unsigned tx_capacity; ++ int nic_arch; ++ int nic_revision; ++ char nic_variant; ++}; ++ ++/*! ++ * Obtain a list of hardware resource mappings, using virtual addresses ++ * ++ * \param vih The handle to identify the efx_vi ++ * \param mdata Pointer to a structure to receive the metadata ++ * \param hw_res_array An array to receive the list of hardware resources ++ * \param length The length of hw_res_array. Updated on success to contain ++ * the number of entries in the supplied array that were used. ++ * \return Zero on success, non-zero on failure ++ */ ++extern int ++efx_vi_hw_resource_get_virt(struct efx_vi_state *vih, ++ struct efx_vi_hw_resource_metadata *mdata, ++ struct efx_vi_hw_resource *hw_res_array, ++ int *length); ++ ++/*! ++ * Obtain a list of hardware resource mappings, using physical addresses ++ * ++ * \param vih The handle to identify the efx_vi ++ * \param mdata Pointer to a structure to receive the metadata ++ * \param hw_res_array An array to receive the list of hardware resources ++ * \param length The length of hw_res_array. Updated on success to contain ++ * the number of entries in the supplied array that were used. ++ * \return Zero on success, non-zero on failure ++ */ ++extern int ++efx_vi_hw_resource_get_phys(struct efx_vi_state *vih, ++ struct efx_vi_hw_resource_metadata *mdata, ++ struct efx_vi_hw_resource *hw_res_array, ++ int *length); ++ ++#endif /* __CI_DRIVER_RESOURCE_EFX_VI_H__ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/driver/resource/linux_efhw_nic.h 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,69 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file contains definition of the public type struct linux_efhw_nic. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * Certain parts of the driver were implemented by ++ * Alexandra Kossovsky ++ * OKTET Labs Ltd, Russia, ++ * http://oktetlabs.ru, ++ * by request of Solarflare Communications ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#ifndef __CI_DRIVER_RESOURCE_LINUX_RESOURCE__ ++#define __CI_DRIVER_RESOURCE_LINUX_RESOURCE__ ++ ++#include ++#include ++ ++ ++/************************************************************************ ++ * Per-nic structure in the resource driver * ++ ************************************************************************/ ++ ++struct linux_efhw_nic { ++ struct efrm_nic efrm_nic; ++ ++ struct pci_dev *pci_dev; /*!< pci descriptor */ ++ struct tasklet_struct tasklet; /*!< for interrupt bottom half */ ++ ++ /* Physical addresses of the control aperture bar. */ ++ unsigned long ctr_ap_pci_addr; ++ ++ /*! Callbacks for driverlink, when needed. */ ++ struct efx_dl_callbacks *dl_callbacks; ++ ++ /*! Event handlers. */ ++ struct efhw_ev_handler *ev_handlers; ++ ++}; ++ ++#define linux_efhw_nic(_efhw_nic) \ ++ container_of(_efhw_nic, struct linux_efhw_nic, efrm_nic.efhw_nic) ++ ++#endif /* __CI_DRIVER_RESOURCE_LINUX_RESOURCE__ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efhw/checks.h 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,118 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file provides helpers to turn bit shifts into dword shifts and ++ * check that the bit fields haven't overflown the dword etc. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#ifndef __CI_EFHW_CHECK_H__ ++#define __CI_EFHW_CHECK_H__ ++ ++/*---------------------------------------------------------------------------- ++ * ++ * Helpers to turn bit shifts into dword shifts and check that the bit fields ++ * haven't overflown the dword etc. Aim is to preserve consistency with the ++ * autogenerated headers - once stable we could hard code. ++ * ++ *---------------------------------------------------------------------------*/ ++ ++/* mask constructors */ ++#define __FALCON_MASK(WIDTH, T) ((((T)1) << (WIDTH)) - 1) ++#define __FALCON_MASK32(WIDTH) __FALCON_MASK((WIDTH), uint32_t) ++#define __FALCON_MASK64(WIDTH) __FALCON_MASK((WIDTH), uint64_t) ++ ++#define __FALCON_MASKFIELD32(LBN, WIDTH) \ ++ ((uint32_t)(__FALCON_MASK32(WIDTH) << (LBN))) ++ ++/* constructors for fields which span the first and second dwords */ ++#define __LW(LBN) (32 - LBN) ++#define __LOW(v, LBN, WIDTH) \ ++ ((uint32_t)(((v) & __FALCON_MASK64(__LW((LBN)))) << (LBN))) ++#define __HIGH(v, LBN, WIDTH) \ ++ ((uint32_t)(((v) >> __LW((LBN))) & \ ++ __FALCON_MASK64((WIDTH - __LW((LBN)))))) ++/* constructors for fields within the second dword */ ++#define __DW2(LBN) ((LBN) - 32) ++ ++/* constructors for fields which span the second and third dwords */ ++#define __LW2(LBN) (64 - LBN) ++#define __LOW2(v, LBN, WIDTH) \ ++ ((uint32_t)(((v) & __FALCON_MASK64(__LW2((LBN)))) << ((LBN) - 32))) ++#define __HIGH2(v, LBN, WIDTH) \ ++ ((uint32_t)(((v) >> __LW2((LBN))) & \ ++ __FALCON_MASK64((WIDTH - __LW2((LBN)))))) ++ ++/* constructors for fields within the third dword */ ++#define __DW3(LBN) ((LBN) - 64) ++ ++/* constructors for fields which span the third and fourth dwords */ ++#define __LW3(LBN) (96 - LBN) ++#define __LOW3(v, LBN, WIDTH) \ ++ ((uint32_t)(((v) & __FALCON_MASK64(__LW3((LBN)))) << ((LBN) - 64))) ++#define __HIGH3(v, LBN, WIDTH) \ ++ ((ci_unit32)(((v) >> __LW3((LBN))) & \ ++ __FALCON_MASK64((WIDTH - __LW3((LBN)))))) ++ ++/* constructors for fields within the fourth dword */ ++#define __DW4(LBN) ((LBN) - 96) ++ ++/* checks that the autogenerated headers are consistent with our model */ ++#define __WIDTHCHCK(a, b) EFHW_ASSERT((a) == (b)) ++#define __RANGECHCK(v, WIDTH) \ ++ EFHW_ASSERT(((uint64_t)(v) & ~(__FALCON_MASK64((WIDTH)))) == 0) ++ ++/* fields within the first dword */ ++#define __DWCHCK(LBN, WIDTH) \ ++ EFHW_ASSERT(((LBN) >= 0) && (((LBN)+(WIDTH)) <= 32)) ++ ++/* fields which span the first and second dwords */ ++#define __LWCHK(LBN, WIDTH) EFHW_ASSERT(WIDTH >= __LW(LBN)) ++ ++/* fields within the second dword */ ++#define __DW2CHCK(LBN, WIDTH) \ ++ EFHW_ASSERT(((LBN) >= 32) && (((LBN)+(WIDTH)) <= 64)) ++ ++/* fields which span the second and third dwords */ ++#define __LW2CHK(LBN, WIDTH) EFHW_ASSERT(WIDTH >= __LW2(LBN)) ++ ++/* fields within the third dword */ ++#define __DW3CHCK(LBN, WIDTH) \ ++ EFHW_ASSERT(((LBN) >= 64) && (((LBN)+(WIDTH)) <= 96)) ++ ++/* fields which span the third and fourth dwords */ ++#define __LW3CHK(LBN, WIDTH) EFHW_ASSERT(WIDTH >= __LW3(LBN)) ++ ++/* fields within the fourth dword */ ++#define __DW4CHCK(LBN, WIDTH) \ ++ EFHW_ASSERT(((LBN) >= 96) && (((LBN)+(WIDTH)) <= 128)) ++ ++/* fields in the first qword */ ++#define __QWCHCK(LBN, WIDTH) \ ++ EFHW_ASSERT(((LBN) >= 0) && (((LBN)+(WIDTH)) <= 64)) ++ ++#endif /* __CI_EFHW_CHECK_H__ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efhw/common.h 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,93 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file provides API of the efhw library which may be used both from ++ * the kernel and from the user-space code. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * Certain parts of the driver were implemented by ++ * Alexandra Kossovsky ++ * OKTET Labs Ltd, Russia, ++ * http://oktetlabs.ru, ++ * by request of Solarflare Communications ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#ifndef __CI_EFHW_COMMON_H__ ++#define __CI_EFHW_COMMON_H__ ++ ++#include ++ ++typedef uint32_t efhw_buffer_addr_t; ++#define EFHW_BUFFER_ADDR_FMT "[ba:%"PRIx32"]" ++ ++/*! Comment? */ ++typedef union { ++ uint64_t u64; ++ struct { ++ uint32_t a; ++ uint32_t b; ++ } opaque; ++} efhw_event_t; ++ ++/* Flags for TX/RX queues */ ++#define EFHW_VI_JUMBO_EN 0x01 /*! scatter RX over multiple desc */ ++#define EFHW_VI_ISCSI_RX_HDIG_EN 0x02 /*! iscsi rx header digest */ ++#define EFHW_VI_ISCSI_TX_HDIG_EN 0x04 /*! iscsi tx header digest */ ++#define EFHW_VI_ISCSI_RX_DDIG_EN 0x08 /*! iscsi rx data digest */ ++#define EFHW_VI_ISCSI_TX_DDIG_EN 0x10 /*! iscsi tx data digest */ ++#define EFHW_VI_TX_PHYS_ADDR_EN 0x20 /*! TX physical address mode */ ++#define EFHW_VI_RX_PHYS_ADDR_EN 0x40 /*! RX physical address mode */ ++#define EFHW_VI_RM_WITH_INTERRUPT 0x80 /*! VI with an interrupt */ ++#define EFHW_VI_TX_IP_CSUM_DIS 0x100 /*! enable ip checksum generation */ ++#define EFHW_VI_TX_TCPUDP_CSUM_DIS 0x200 /*! enable tcp/udp checksum ++ generation */ ++#define EFHW_VI_TX_TCPUDP_ONLY 0x400 /*! drop non-tcp/udp packets */ ++ ++/* Types of hardware filter */ ++/* Each of these values implicitly selects scatter filters on B0 - or in ++ EFHW_IP_FILTER_TYPE_NOSCAT_B0_MASK if a non-scatter filter is required */ ++#define EFHW_IP_FILTER_TYPE_UDP_WILDCARD (0) /* dest host only */ ++#define EFHW_IP_FILTER_TYPE_UDP_FULL (1) /* dest host and port */ ++#define EFHW_IP_FILTER_TYPE_TCP_WILDCARD (2) /* dest based filter */ ++#define EFHW_IP_FILTER_TYPE_TCP_FULL (3) /* src filter */ ++/* Same again, but with RSS (for B0 only) */ ++#define EFHW_IP_FILTER_TYPE_UDP_WILDCARD_RSS_B0 (4) ++#define EFHW_IP_FILTER_TYPE_UDP_FULL_RSS_B0 (5) ++#define EFHW_IP_FILTER_TYPE_TCP_WILDCARD_RSS_B0 (6) ++#define EFHW_IP_FILTER_TYPE_TCP_FULL_RSS_B0 (7) ++ ++#define EFHW_IP_FILTER_TYPE_FULL_MASK (0x1) /* Mask for full / wildcard */ ++#define EFHW_IP_FILTER_TYPE_TCP_MASK (0x2) /* Mask for TCP type */ ++#define EFHW_IP_FILTER_TYPE_RSS_B0_MASK (0x4) /* Mask for B0 RSS enable */ ++#define EFHW_IP_FILTER_TYPE_NOSCAT_B0_MASK (0x8) /* Mask for B0 SCATTER dsbl */ ++ ++#define EFHW_IP_FILTER_TYPE_MASK (0xffff) /* Mask of types above */ ++ ++#define EFHW_IP_FILTER_BROADCAST (0x10000) /* driverlink filter ++ support */ ++ ++#endif /* __CI_EFHW_COMMON_H__ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efhw/common_sysdep.h 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,61 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file provides version-independent Linux kernel API for ++ * userland-to-kernel interfaces. ++ * Only kernels >=2.6.9 are supported. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * Certain parts of the driver were implemented by ++ * Alexandra Kossovsky ++ * OKTET Labs Ltd, Russia, ++ * http://oktetlabs.ru, ++ * by request of Solarflare Communications ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#ifndef __CI_EFHW_COMMON_LINUX_H__ ++#define __CI_EFHW_COMMON_LINUX_H__ ++ ++#include ++ ++/* Dirty hack, but Linux kernel does not provide DMA_ADDR_T_FMT */ ++#if BITS_PER_LONG == 64 || defined(CONFIG_HIGHMEM64G) ++#define DMA_ADDR_T_FMT "%llx" ++#else ++#define DMA_ADDR_T_FMT "%x" ++#endif ++ ++/* Linux kernel also does not provide PRIx32... Sigh. */ ++#define PRIx32 "x" ++ ++#ifdef __ia64__ ++# define PRIx64 "lx" ++#else ++# define PRIx64 "llx" ++#endif ++ ++#endif /* __CI_EFHW_COMMON_LINUX_H__ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efhw/debug.h 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,84 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file provides debug-related API for efhw library using Linux kernel ++ * primitives. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * Certain parts of the driver were implemented by ++ * Alexandra Kossovsky ++ * OKTET Labs Ltd, Russia, ++ * http://oktetlabs.ru, ++ * by request of Solarflare Communications ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#ifndef __CI_EFHW_DEBUG_LINUX_H__ ++#define __CI_EFHW_DEBUG_LINUX_H__ ++ ++#define EFHW_PRINTK_PREFIX "[sfc efhw] " ++ ++#define EFHW_PRINTK(level, fmt, ...) \ ++ printk(level EFHW_PRINTK_PREFIX fmt "\n", __VA_ARGS__) ++ ++/* Following macros should be used with non-zero format parameters ++ * due to __VA_ARGS__ limitations. Use "%s" with __func__ if you can't ++ * find better parameters. */ ++#define EFHW_ERR(fmt, ...) EFHW_PRINTK(KERN_ERR, fmt, __VA_ARGS__) ++#define EFHW_WARN(fmt, ...) EFHW_PRINTK(KERN_WARNING, fmt, __VA_ARGS__) ++#define EFHW_NOTICE(fmt, ...) EFHW_PRINTK(KERN_NOTICE, fmt, __VA_ARGS__) ++#if 0 && !defined(NDEBUG) ++#define EFHW_TRACE(fmt, ...) EFHW_PRINTK(KERN_DEBUG, fmt, __VA_ARGS__) ++#else ++#define EFHW_TRACE(fmt, ...) ++#endif ++ ++#ifndef NDEBUG ++#define EFHW_ASSERT(cond) BUG_ON((cond) == 0) ++#define EFHW_DO_DEBUG(expr) expr ++#else ++#define EFHW_ASSERT(cond) ++#define EFHW_DO_DEBUG(expr) ++#endif ++ ++#define EFHW_TEST(expr) \ ++ do { \ ++ if (unlikely(!(expr))) \ ++ BUG(); \ ++ } while (0) ++ ++/* Build time asserts. We paste the line number into the type name ++ * so that the macro can be used more than once per file even if the ++ * compiler objects to multiple identical typedefs. Collisions ++ * between use in different header files is still possible. */ ++#ifndef EFHW_BUILD_ASSERT ++#define __EFHW_BUILD_ASSERT_NAME(_x) __EFHW_BUILD_ASSERT_ILOATHECPP(_x) ++#define __EFHW_BUILD_ASSERT_ILOATHECPP(_x) __EFHW_BUILD_ASSERT__ ##_x ++#define EFHW_BUILD_ASSERT(e) \ ++ typedef char __EFHW_BUILD_ASSERT_NAME(__LINE__)[(e) ? 1 : -1] ++#endif ++ ++#endif /* __CI_EFHW_DEBUG_LINUX_H__ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efhw/efhw_config.h 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,43 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file provides some limits used in both kernel and userland code. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * Certain parts of the driver were implemented by ++ * Alexandra Kossovsky ++ * OKTET Labs Ltd, Russia, ++ * http://oktetlabs.ru, ++ * by request of Solarflare Communications ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#ifndef __CI_EFHW_EFAB_CONFIG_H__ ++#define __CI_EFHW_EFAB_CONFIG_H__ ++ ++#define EFHW_MAX_NR_DEVS 5 /* max number of efhw devices supported */ ++ ++#endif /* __CI_EFHW_EFAB_CONFIG_H__ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efhw/efhw_types.h 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,382 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file provides struct efhw_nic and some related types. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * Certain parts of the driver were implemented by ++ * Alexandra Kossovsky ++ * OKTET Labs Ltd, Russia, ++ * http://oktetlabs.ru, ++ * by request of Solarflare Communications ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#ifndef __CI_EFHW_EFAB_TYPES_H__ ++#define __CI_EFHW_EFAB_TYPES_H__ ++ ++#include ++#include ++#include ++#include ++ ++/*-------------------------------------------------------------------- ++ * ++ * forward type declarations ++ * ++ *--------------------------------------------------------------------*/ ++ ++struct efhw_nic; ++ ++/*-------------------------------------------------------------------- ++ * ++ * Managed interface ++ * ++ *--------------------------------------------------------------------*/ ++ ++struct efhw_buffer_table_allocation{ ++ unsigned base; ++ unsigned order; ++}; ++ ++struct eventq_resource_hardware { ++ /*!iobuffer allocated for eventq - can be larger than eventq */ ++ struct efhw_iopages iobuff; ++ unsigned iobuff_off; ++ struct efhw_buffer_table_allocation buf_tbl_alloc; ++ int capacity; /*!< capacity of event queue */ ++}; ++ ++/*-------------------------------------------------------------------- ++ * ++ * event queues and event driven callbacks ++ * ++ *--------------------------------------------------------------------*/ ++ ++struct efhw_keventq { ++ int lock; ++ caddr_t evq_base; ++ int32_t evq_ptr; ++ uint32_t evq_mask; ++ unsigned instance; ++ struct eventq_resource_hardware hw; ++ struct efhw_ev_handler *ev_handlers; ++}; ++ ++/*-------------------------------------------------------------------- ++ * ++ * filters ++ * ++ *--------------------------------------------------------------------*/ ++ ++struct efhw_filter_spec { ++ uint dmaq_id; ++ uint32_t saddr_le32; ++ uint32_t daddr_le32; ++ uint16_t sport_le16; ++ uint16_t dport_le16; ++ unsigned tcp : 1; ++ unsigned full : 1; ++ unsigned rss : 1; /* not supported on A1 */ ++ unsigned scatter : 1; /* not supported on A1 */ ++}; ++ ++struct efhw_filter_depth { ++ unsigned needed; ++ unsigned max; ++}; ++ ++struct efhw_filter_search_limits { ++ unsigned tcp_full; ++ unsigned tcp_wild; ++ unsigned udp_full; ++ unsigned udp_wild; ++}; ++ ++ ++/********************************************************************** ++ * Portable HW interface. *************************************** ++ **********************************************************************/ ++ ++/*-------------------------------------------------------------------- ++ * ++ * EtherFabric Functional units - configuration and control ++ * ++ *--------------------------------------------------------------------*/ ++ ++struct efhw_func_ops { ++ ++ /*-------------- Initialisation ------------ */ ++ ++ /*! close down all hardware functional units - leaves NIC in a safe ++ state for driver unload */ ++ void (*close_hardware) (struct efhw_nic *nic); ++ ++ /*! initialise all hardware functional units */ ++ int (*init_hardware) (struct efhw_nic *nic, ++ struct efhw_ev_handler *, ++ const uint8_t *mac_addr, int non_irq_evq); ++ ++ /*-------------- Interrupt support ------------ */ ++ ++ /*! Main interrupt routine ++ ** This function returns, ++ ** - zero, if the IRQ was not generated by EF1 ++ ** - non-zero, if EF1 was the source of the IRQ ++ ** ++ ** ++ ** opaque is an OS provided pointer for use by the OS callbacks ++ ** e.g in Windows used to indicate DPC scheduled ++ */ ++ int (*interrupt) (struct efhw_nic *nic); ++ ++ /*! Enable the interrupt */ ++ void (*interrupt_enable) (struct efhw_nic *nic); ++ ++ /*! Disable the interrupt */ ++ void (*interrupt_disable) (struct efhw_nic *nic); ++ ++ /*! Set interrupt moderation strategy for the given IRQ unit ++ ** val is in usec ++ */ ++ void (*set_interrupt_moderation)(struct efhw_nic *nic, int evq, ++ uint val); ++ ++ /*-------------- Event support ------------ */ ++ ++ /*! Enable the given event queue ++ depending on the underlying implementation (EF1 or Falcon) then ++ either a q_base_addr in host memory, or a buffer base id should ++ be proivded ++ */ ++ void (*event_queue_enable) (struct efhw_nic *nic, ++ uint evq, /* evnt queue index */ ++ uint evq_size, /* units of #entries */ ++ dma_addr_t q_base_addr, uint buf_base_id, ++ int interrupting); ++ ++ /*! Disable the given event queue (and any associated timer) */ ++ void (*event_queue_disable) (struct efhw_nic *nic, uint evq, ++ int timer_only); ++ ++ /*! request wakeup from the NIC on a given event Q */ ++ void (*wakeup_request) (struct efhw_nic *nic, dma_addr_t q_base_addr, ++ int next_i, int evq); ++ ++ /*! Push a SW event on a given eventQ */ ++ void (*sw_event) (struct efhw_nic *nic, int data, int evq); ++ ++ /*-------------- IP Filter API ------------ */ ++ ++ /*! Setup a given filter - The software can request a filter_i, ++ * but some EtherFabric implementations will override with ++ * a more suitable index ++ */ ++ int (*ipfilter_set) (struct efhw_nic *nic, int type, ++ int *filter_i, int dmaq, ++ unsigned saddr_be32, unsigned sport_be16, ++ unsigned daddr_be32, unsigned dport_be16); ++ ++ /*! Clear down a given filter */ ++ void (*ipfilter_clear) (struct efhw_nic *nic, int filter_idx); ++ ++ /*-------------- DMA support ------------ */ ++ ++ /*! Initialise NIC state for a given TX DMAQ */ ++ void (*dmaq_tx_q_init) (struct efhw_nic *nic, ++ uint dmaq, uint evq, uint owner, uint tag, ++ uint dmaq_size, uint buf_idx, uint flags); ++ ++ /*! Initialise NIC state for a given RX DMAQ */ ++ void (*dmaq_rx_q_init) (struct efhw_nic *nic, ++ uint dmaq, uint evq, uint owner, uint tag, ++ uint dmaq_size, uint buf_idx, uint flags); ++ ++ /*! Disable a given TX DMAQ */ ++ void (*dmaq_tx_q_disable) (struct efhw_nic *nic, uint dmaq); ++ ++ /*! Disable a given RX DMAQ */ ++ void (*dmaq_rx_q_disable) (struct efhw_nic *nic, uint dmaq); ++ ++ /*! Flush a given TX DMA channel */ ++ int (*flush_tx_dma_channel) (struct efhw_nic *nic, uint dmaq); ++ ++ /*! Flush a given RX DMA channel */ ++ int (*flush_rx_dma_channel) (struct efhw_nic *nic, uint dmaq); ++ ++ /*-------------- Buffer table Support ------------ */ ++ ++ /*! Initialise a buffer table page */ ++ void (*buffer_table_set) (struct efhw_nic *nic, ++ dma_addr_t dma_addr, ++ uint bufsz, uint region, ++ int own_id, int buffer_id); ++ ++ /*! Initialise a block of buffer table pages */ ++ void (*buffer_table_set_n) (struct efhw_nic *nic, int buffer_id, ++ dma_addr_t dma_addr, ++ uint bufsz, uint region, ++ int n_pages, int own_id); ++ ++ /*! Clear a block of buffer table pages */ ++ void (*buffer_table_clear) (struct efhw_nic *nic, int buffer_id, ++ int num); ++ ++ /*! Commit a buffer table update */ ++ void (*buffer_table_commit) (struct efhw_nic *nic); ++ ++ /*-------------- New filter API ------------ */ ++ ++ /*! Set a given filter */ ++ int (*filter_set) (struct efhw_nic *nic, struct efhw_filter_spec *spec, ++ int *filter_idx_out); ++ ++ /*! Clear a given filter */ ++ void (*filter_clear) (struct efhw_nic *nic, int filter_idx); ++}; ++ ++ ++/*---------------------------------------------------------------------------- ++ * ++ * NIC type ++ * ++ *---------------------------------------------------------------------------*/ ++ ++struct efhw_device_type { ++ int arch; /* enum efhw_arch */ ++ char variant; /* 'A', 'B', ... */ ++ int revision; /* 0, 1, ... */ ++}; ++ ++ ++/*---------------------------------------------------------------------------- ++ * ++ * EtherFabric NIC instance - nic.c for HW independent functions ++ * ++ *---------------------------------------------------------------------------*/ ++ ++/*! */ ++struct efhw_nic { ++ /*! zero base index in efrm_nic_tablep->nic array */ ++ int index; ++ int ifindex; /*!< OS level nic index */ ++ struct net *nd_net; ++ ++ struct efhw_device_type devtype; ++ ++ /*! Options that can be set by user. */ ++ unsigned options; ++# define NIC_OPT_EFTEST 0x1 /* owner is an eftest app */ ++ ++# define NIC_OPT_DEFAULT 0 ++ ++ /*! Internal flags that indicate hardware properties at runtime. */ ++ unsigned flags; ++# define NIC_FLAG_NO_INTERRUPT 0x01 /* to be set at init time only */ ++# define NIC_FLAG_TRY_MSI 0x02 ++# define NIC_FLAG_MSI 0x04 ++# define NIC_FLAG_OS_IRQ_EN 0x08 ++ ++ unsigned mtu; /*!< MAC MTU (includes MAC hdr) */ ++ ++ /* hardware resources */ ++ ++ /*! I/O address of the start of the bar */ ++ volatile char __iomem *bar_ioaddr; ++ ++ /*! Bar number of control aperture. */ ++ unsigned ctr_ap_bar; ++ /*! Length of control aperture in bytes. */ ++ unsigned ctr_ap_bytes; ++ ++ uint8_t mac_addr[ETH_ALEN]; /*!< mac address */ ++ ++ /*! EtherFabric Functional Units -- functions */ ++ const struct efhw_func_ops *efhw_func; ++ ++ /*! This lock protects a number of misc NIC resources. It should ++ * only be used for things that can be at the bottom of the lock ++ * order. ie. You mustn't attempt to grab any other lock while ++ * holding this one. ++ */ ++ spinlock_t *reg_lock; ++ spinlock_t the_reg_lock; ++ ++ int buf_commit_outstanding; /*!< outstanding buffer commits */ ++ ++ /*! interrupt callbacks (hard-irq) */ ++ void (*irq_handler) (struct efhw_nic *, int unit); ++ ++ /*! event queues per driver */ ++ struct efhw_keventq interrupting_evq; ++ ++/* for marking when we are not using an IRQ unit ++ - 0 is a valid offset to an IRQ unit on EF1! */ ++#define EFHW_IRQ_UNIT_UNUSED 0xffff ++ /*! interrupt unit in use for the interrupting event queue */ ++ unsigned int irq_unit; ++ ++ struct efhw_keventq non_interrupting_evq; ++ ++ struct efhw_iopage irq_iobuff; /*!< Falcon SYSERR interrupt */ ++ ++ /* The new driverlink infrastructure. */ ++ struct efx_dl_device *net_driver_dev; ++ struct efx_dlfilt_cb_s *dlfilter_cb; ++ ++ /*! Bit masks of the sizes of event queues and dma queues supported ++ * by the nic. */ ++ unsigned evq_sizes; ++ unsigned rxq_sizes; ++ unsigned txq_sizes; ++ ++ /* Size of filter table. */ ++ unsigned ip_filter_tbl_size; ++ ++ /* Number of filters currently used */ ++ unsigned ip_filter_tbl_used; ++ ++ /* Dynamically allocated filter state. */ ++ uint8_t *filter_in_use; ++ struct efhw_filter_spec *filter_spec_cache; ++ ++ /* Currently required and maximum filter table search depths. */ ++ struct efhw_filter_depth tcp_full_srch; ++ struct efhw_filter_depth tcp_wild_srch; ++ struct efhw_filter_depth udp_full_srch; ++ struct efhw_filter_depth udp_wild_srch; ++ ++ /* Number of event queues, DMA queues and timers. */ ++ unsigned num_evqs; ++ unsigned num_dmaqs; ++ unsigned num_timers; ++}; ++ ++ ++#define EFHW_KVA(nic) ((nic)->bar_ioaddr) ++ ++ ++#endif /* __CI_EFHW_EFHW_TYPES_H__ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efhw/eventq.h 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,72 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file contains API provided by efhw/eventq.c file. This file is not ++ * designed for use outside of the SFC resource driver. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * Certain parts of the driver were implemented by ++ * Alexandra Kossovsky ++ * OKTET Labs Ltd, Russia, ++ * http://oktetlabs.ru, ++ * by request of Solarflare Communications ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#ifndef __CI_EFHW_EVENTQ_H__ ++#define __CI_EFHW_EVENTQ_H__ ++ ++#include ++#include ++ ++/*! Poll the event queue. */ ++extern int efhw_keventq_poll(struct efhw_nic *, struct efhw_keventq *); ++ ++/*! Callbacks for handling events. */ ++struct efhw_ev_handler { ++ void (*wakeup_fn)(struct efhw_nic *nic, unsigned); ++ void (*timeout_fn)(struct efhw_nic *nic, unsigned); ++ void (*dmaq_flushed_fn) (struct efhw_nic *, unsigned, int); ++}; ++ ++extern int efhw_keventq_ctor(struct efhw_nic *, int instance, ++ struct efhw_keventq *, struct efhw_ev_handler *); ++extern void efhw_keventq_dtor(struct efhw_nic *, struct efhw_keventq *); ++ ++extern void efhw_handle_txdmaq_flushed(struct efhw_nic *, ++ struct efhw_ev_handler *, ++ efhw_event_t *); ++extern void efhw_handle_rxdmaq_flushed(struct efhw_nic *, ++ struct efhw_ev_handler *, ++ efhw_event_t *); ++extern void efhw_handle_wakeup_event(struct efhw_nic *, ++ struct efhw_ev_handler *, ++ efhw_event_t *); ++extern void efhw_handle_timeout_event(struct efhw_nic *, ++ struct efhw_ev_handler *, ++ efhw_event_t *); ++ ++#endif /* __CI_EFHW_EVENTQ_H__ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efhw/eventq_macros.h 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,77 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file provides some event-related macros. This file is designed for ++ * use from kernel and from the userland contexts. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * Certain parts of the driver were implemented by ++ * Alexandra Kossovsky ++ * OKTET Labs Ltd, Russia, ++ * http://oktetlabs.ru, ++ * by request of Solarflare Communications ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#ifndef __CI_EFHW_EVENTQ_MACROS_H__ ++#define __CI_EFHW_EVENTQ_MACROS_H__ ++ ++#include ++ ++/*-------------------------------------------------------------------- ++ * ++ * Event Queue manipulation ++ * ++ *--------------------------------------------------------------------*/ ++ ++#define EFHW_EVENT_OFFSET(q, s, i) \ ++ (((s)->evq_ptr - (i) * (int32_t)sizeof(efhw_event_t)) \ ++ & (q)->evq_mask) ++ ++#define EFHW_EVENT_PTR(q, s, i) \ ++ ((efhw_event_t *)((q)->evq_base + EFHW_EVENT_OFFSET(q, s, i))) ++ ++#define EFHW_EVENTQ_NEXT(s) \ ++ do { ((s)->evq_ptr += sizeof(efhw_event_t)); } while (0) ++ ++#define EFHW_EVENTQ_PREV(s) \ ++ do { ((s)->evq_ptr -= sizeof(efhw_event_t)); } while (0) ++ ++/* Be worried about this on byteswapped machines */ ++/* Due to crazy chipsets, we see the event words being written in ++** arbitrary order (bug4539). So test for presence of event must ensure ++** that both halves have changed from the null. ++*/ ++#define EFHW_IS_EVENT(evp) \ ++ (((evp)->opaque.a != (uint32_t)-1) && \ ++ ((evp)->opaque.b != (uint32_t)-1)) ++#define EFHW_CLEAR_EVENT(evp) ((evp)->u64 = (uint64_t)-1) ++#define EFHW_CLEAR_EVENT_VALUE 0xff ++ ++#define EFHW_EVENT_OVERFLOW(evq, s) \ ++ (EFHW_IS_EVENT(EFHW_EVENT_PTR(evq, s, 1))) ++ ++#endif /* __CI_EFHW_EVENTQ_MACROS_H__ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efhw/falcon.h 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,94 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file contains API provided by efhw/falcon.c file. This file is not ++ * designed for use outside of the SFC resource driver. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * Certain parts of the driver were implemented by ++ * Alexandra Kossovsky ++ * OKTET Labs Ltd, Russia, ++ * http://oktetlabs.ru, ++ * by request of Solarflare Communications ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#ifndef __CI_EFHW_FALCON_H__ ++#define __CI_EFHW_FALCON_H__ ++ ++#include ++#include ++ ++/*---------------------------------------------------------------------------- ++ * ++ * Locks - unfortunately required ++ * ++ *---------------------------------------------------------------------------*/ ++ ++#define FALCON_LOCK_DECL irq_flags_t lock_state ++#define FALCON_LOCK_LOCK(nic) \ ++ spin_lock_irqsave((nic)->reg_lock, lock_state) ++#define FALCON_LOCK_UNLOCK(nic) \ ++ spin_unlock_irqrestore((nic)->reg_lock, lock_state) ++ ++extern struct efhw_func_ops falcon_char_functional_units; ++ ++/*! specify a pace value for a TX DMA Queue */ ++extern void falcon_nic_pace(struct efhw_nic *nic, uint dmaq, uint pace); ++ ++/*! configure the pace engine */ ++extern void falcon_nic_pace_cfg(struct efhw_nic *nic, int fb_base, ++ int bin_thresh); ++ ++/*! confirm buffer table updates - should be used for items where ++ loss of data would be unacceptable. E.g for the buffers that back ++ an event or DMA queue */ ++extern void falcon_nic_buffer_table_confirm(struct efhw_nic *nic); ++ ++/*! Reset the all the TX DMA queue pointers. */ ++extern void falcon_clobber_tx_dma_ptrs(struct efhw_nic *nic, uint dmaq); ++ ++extern int ++falcon_handle_char_event(struct efhw_nic *nic, ++ struct efhw_ev_handler *h, efhw_event_t *evp); ++ ++/*! Acknowledge to HW that processing is complete on a given event queue */ ++extern void falcon_nic_evq_ack(struct efhw_nic *nic, uint evq, /* evq id */ ++ uint rptr, /* new read pointer update */ ++ bool wakeup /* request a wakeup event if ++ ptr's != */ ++ ); ++ ++extern void ++falcon_nic_buffer_table_set_n(struct efhw_nic *nic, int buffer_id, ++ dma_addr_t dma_addr, uint bufsz, uint region, ++ int n_pages, int own_id); ++ ++extern int falcon_nic_filter_ctor(struct efhw_nic *nic); ++ ++extern void falcon_nic_filter_dtor(struct efhw_nic *nic); ++ ++#endif /* __CI_EFHW_FALCON_H__ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efhw/falcon_hash.h 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,58 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file contains API provided by efhw/falcon_hash.c file. ++ * Function declared in this file are not exported from the Linux ++ * sfc_resource driver. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * Certain parts of the driver were implemented by ++ * Alexandra Kossovsky ++ * OKTET Labs Ltd, Russia, ++ * http://oktetlabs.ru, ++ * by request of Solarflare Communications ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#ifndef __CI_EFHW_FALCON_HASH_H__ ++#define __CI_EFHW_FALCON_HASH_H__ ++ ++extern unsigned int ++falcon_hash_get_ip_key(unsigned int src_ip, unsigned int src_port, ++ unsigned int dest_ip, unsigned int dest_port, ++ int tcp, int full); ++ ++extern unsigned int ++falcon_hash_function1(unsigned int key, unsigned int nfilters); ++ ++extern unsigned int ++falcon_hash_function2(unsigned int key, unsigned int nfilters); ++ ++extern unsigned int ++falcon_hash_iterator(unsigned int hash1, unsigned int hash2, ++ unsigned int n_search, unsigned int nfilters); ++ ++#endif /* __CI_EFHW_FALCON_HASH_H__ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efhw/hardware_sysdep.h 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,69 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file provides version-independent Linux kernel API for header files ++ * with hardware-related definitions (in ci/driver/efab/hardware*). ++ * Only kernels >=2.6.9 are supported. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * Certain parts of the driver were implemented by ++ * Alexandra Kossovsky ++ * OKTET Labs Ltd, Russia, ++ * http://oktetlabs.ru, ++ * by request of Solarflare Communications ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#ifndef __CI_EFHW_HARDWARE_LINUX_H__ ++#define __CI_EFHW_HARDWARE_LINUX_H__ ++ ++#include ++ ++#ifdef __LITTLE_ENDIAN ++#define EFHW_IS_LITTLE_ENDIAN ++#elif __BIG_ENDIAN ++#define EFHW_IS_BIG_ENDIAN ++#else ++#error Unknown endianness ++#endif ++ ++#ifndef readq ++static inline uint64_t __readq(volatile void __iomem *addr) ++{ ++ return *(volatile uint64_t *)addr; ++} ++#define readq(x) __readq(x) ++#endif ++ ++#ifndef writeq ++static inline void __writeq(uint64_t v, volatile void __iomem *addr) ++{ ++ *(volatile uint64_t *)addr = v; ++} ++#define writeq(val, addr) __writeq((val), (addr)) ++#endif ++ ++#endif /* __CI_EFHW_HARDWARE_LINUX_H__ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efhw/iopage.h 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,58 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file contains OS-independent API for allocating iopage types. ++ * The implementation of these functions is highly OS-dependent. ++ * This file is not designed for use outside of the SFC resource driver. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * Certain parts of the driver were implemented by ++ * Alexandra Kossovsky ++ * OKTET Labs Ltd, Russia, ++ * http://oktetlabs.ru, ++ * by request of Solarflare Communications ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#ifndef __CI_DRIVER_RESOURCE_IOPAGE_H__ ++#define __CI_DRIVER_RESOURCE_IOPAGE_H__ ++ ++#include ++ ++/*-------------------------------------------------------------------- ++ * ++ * memory allocation ++ * ++ *--------------------------------------------------------------------*/ ++ ++extern int efhw_iopage_alloc(struct efhw_nic *, struct efhw_iopage *p); ++extern void efhw_iopage_free(struct efhw_nic *, struct efhw_iopage *p); ++ ++extern int efhw_iopages_alloc(struct efhw_nic *, struct efhw_iopages *p, ++ unsigned order); ++extern void efhw_iopages_free(struct efhw_nic *, struct efhw_iopages *p); ++ ++#endif /* __CI_DRIVER_RESOURCE_IOPAGE_H__ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efhw/iopage_types.h 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,190 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file provides struct efhw_page and struct efhw_iopage for Linux ++ * kernel. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * Certain parts of the driver were implemented by ++ * Alexandra Kossovsky ++ * OKTET Labs Ltd, Russia, ++ * http://oktetlabs.ru, ++ * by request of Solarflare Communications ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#ifndef __CI_EFHW_IOPAGE_LINUX_H__ ++#define __CI_EFHW_IOPAGE_LINUX_H__ ++ ++#include ++#include ++#include ++#include ++ ++/*-------------------------------------------------------------------- ++ * ++ * struct efhw_page: A single page of memory. Directly mapped in the ++ * driver, and can be mapped to userlevel. ++ * ++ *--------------------------------------------------------------------*/ ++ ++struct efhw_page { ++ unsigned long kva; ++}; ++ ++static inline int efhw_page_alloc(struct efhw_page *p) ++{ ++ p->kva = __get_free_page(in_interrupt()? GFP_ATOMIC : GFP_KERNEL); ++ return p->kva ? 0 : -ENOMEM; ++} ++ ++static inline int efhw_page_alloc_zeroed(struct efhw_page *p) ++{ ++ p->kva = get_zeroed_page(in_interrupt()? GFP_ATOMIC : GFP_KERNEL); ++ return p->kva ? 0 : -ENOMEM; ++} ++ ++static inline void efhw_page_free(struct efhw_page *p) ++{ ++ free_page(p->kva); ++ EFHW_DO_DEBUG(memset(p, 0, sizeof(*p))); ++} ++ ++static inline char *efhw_page_ptr(struct efhw_page *p) ++{ ++ return (char *)p->kva; ++} ++ ++static inline unsigned efhw_page_pfn(struct efhw_page *p) ++{ ++ return (unsigned)(__pa(p->kva) >> PAGE_SHIFT); ++} ++ ++static inline void efhw_page_mark_invalid(struct efhw_page *p) ++{ ++ p->kva = 0; ++} ++ ++static inline int efhw_page_is_valid(struct efhw_page *p) ++{ ++ return p->kva != 0; ++} ++ ++static inline void efhw_page_init_from_va(struct efhw_page *p, void *va) ++{ ++ p->kva = (unsigned long)va; ++} ++ ++/*-------------------------------------------------------------------- ++ * ++ * struct efhw_iopage: A single page of memory. Directly mapped in the driver, ++ * and can be mapped to userlevel. Can also be accessed by the NIC. ++ * ++ *--------------------------------------------------------------------*/ ++ ++struct efhw_iopage { ++ struct efhw_page p; ++ dma_addr_t dma_addr; ++}; ++ ++static inline dma_addr_t efhw_iopage_dma_addr(struct efhw_iopage *p) ++{ ++ return p->dma_addr; ++} ++ ++#define efhw_iopage_ptr(iop) efhw_page_ptr(&(iop)->p) ++#define efhw_iopage_pfn(iop) efhw_page_pfn(&(iop)->p) ++#define efhw_iopage_mark_invalid(iop) efhw_page_mark_invalid(&(iop)->p) ++#define efhw_iopage_is_valid(iop) efhw_page_is_valid(&(iop)->p) ++ ++/*-------------------------------------------------------------------- ++ * ++ * struct efhw_iopages: A set of pages that are contiguous in physical ++ * memory. Directly mapped in the driver, and can be mapped to userlevel. ++ * Can also be accessed by the NIC. ++ * ++ * NB. The O/S may be unwilling to allocate many, or even any of these. So ++ * only use this type where the NIC really needs a physically contiguous ++ * buffer. ++ * ++ *--------------------------------------------------------------------*/ ++ ++struct efhw_iopages { ++ caddr_t kva; ++ unsigned order; ++ dma_addr_t dma_addr; ++}; ++ ++static inline caddr_t efhw_iopages_ptr(struct efhw_iopages *p) ++{ ++ return p->kva; ++} ++ ++static inline unsigned efhw_iopages_pfn(struct efhw_iopages *p) ++{ ++ return (unsigned)(__pa(p->kva) >> PAGE_SHIFT); ++} ++ ++static inline dma_addr_t efhw_iopages_dma_addr(struct efhw_iopages *p) ++{ ++ return p->dma_addr; ++} ++ ++static inline unsigned efhw_iopages_size(struct efhw_iopages *p) ++{ ++ return 1u << (p->order + PAGE_SHIFT); ++} ++ ++/* struct efhw_iopage <-> struct efhw_iopages conversions for handling ++ * physically contiguous allocations in iobufsets for iSCSI. This allows ++ * the essential information about contiguous allocations from ++ * efhw_iopages_alloc() to be saved away in the struct efhw_iopage array in ++ * an iobufset. (Changing the iobufset resource to use a union type would ++ * involve a lot of code changes, and make the iobufset's metadata larger ++ * which could be bad as it's supposed to fit into a single page on some ++ * platforms.) ++ */ ++static inline void ++efhw_iopage_init_from_iopages(struct efhw_iopage *iopage, ++ struct efhw_iopages *iopages, unsigned pageno) ++{ ++ iopage->p.kva = ((unsigned long)efhw_iopages_ptr(iopages)) ++ + (pageno * PAGE_SIZE); ++ iopage->dma_addr = efhw_iopages_dma_addr(iopages) + ++ (pageno * PAGE_SIZE); ++} ++ ++static inline void ++efhw_iopages_init_from_iopage(struct efhw_iopages *iopages, ++ struct efhw_iopage *iopage, unsigned order) ++{ ++ iopages->kva = (caddr_t) efhw_iopage_ptr(iopage); ++ EFHW_ASSERT(iopages->kva); ++ iopages->order = order; ++ iopages->dma_addr = efhw_iopage_dma_addr(iopage); ++} ++ ++#endif /* __CI_EFHW_IOPAGE_LINUX_H__ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efhw/nic.h 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,62 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file contains API provided by efhw/nic.c file. This file is not ++ * designed for use outside of the SFC resource driver. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * Certain parts of the driver were implemented by ++ * Alexandra Kossovsky ++ * OKTET Labs Ltd, Russia, ++ * http://oktetlabs.ru, ++ * by request of Solarflare Communications ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#ifndef __CI_EFHW_NIC_H__ ++#define __CI_EFHW_NIC_H__ ++ ++#include ++#include ++ ++ ++/* Convert PCI info to device type. Returns false when device is not ++ * recognised. ++ */ ++extern int efhw_device_type_init(struct efhw_device_type *dt, ++ int vendor_id, int device_id, int revision); ++ ++/* Initialise fields that do not involve touching hardware. */ ++extern void efhw_nic_init(struct efhw_nic *nic, unsigned flags, ++ unsigned options, struct efhw_device_type dev_type); ++ ++/*! Destruct NIC resources */ ++extern void efhw_nic_dtor(struct efhw_nic *nic); ++ ++/*! Shutdown interrupts */ ++extern void efhw_nic_close_interrupts(struct efhw_nic *nic); ++ ++#endif /* __CI_EFHW_NIC_H__ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efhw/public.h 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,104 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file provides public API of efhw library exported from the SFC ++ * resource driver. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * Certain parts of the driver were implemented by ++ * Alexandra Kossovsky ++ * OKTET Labs Ltd, Russia, ++ * http://oktetlabs.ru, ++ * by request of Solarflare Communications ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#ifndef __CI_EFHW_PUBLIC_H__ ++#define __CI_EFHW_PUBLIC_H__ ++ ++#include ++#include ++ ++/*! Returns true if we have some EtherFabric functional units - ++ whether configured or not */ ++static inline int efhw_nic_have_functional_units(struct efhw_nic *nic) ++{ ++ return nic->efhw_func != 0; ++} ++ ++/*! Returns true if the EtherFabric functional units have been configured */ ++static inline int efhw_nic_have_hw(struct efhw_nic *nic) ++{ ++ return efhw_nic_have_functional_units(nic) && (EFHW_KVA(nic) != 0); ++} ++ ++/*! Helper function to allocate the iobuffer needed by an eventq ++ * - it ensures the eventq has the correct alignment for the NIC ++ * ++ * \param rm Event-queue resource manager ++ * \param instance Event-queue instance (index) ++ * \param buf_bytes Requested size of eventq ++ * \return < 0 if iobuffer allocation fails ++ */ ++int efhw_nic_event_queue_alloc_iobuffer(struct efhw_nic *nic, ++ struct eventq_resource_hardware *h, ++ int evq_instance, unsigned buf_bytes); ++ ++extern void falcon_nic_set_rx_usr_buf_size(struct efhw_nic *, ++ int rx_usr_buf_size); ++ ++/*! Get RX filter search limits from RX_FILTER_CTL_REG. ++ * use_raw_values = 0 to get actual depth of search, or 1 to get raw values ++ * from register. ++ */ ++extern void ++falcon_nic_get_rx_filter_search_limits(struct efhw_nic *nic, ++ struct efhw_filter_search_limits *lim, ++ int use_raw_values); ++ ++/*! Set RX filter search limits in RX_FILTER_CTL_REG. ++ * use_raw_values = 0 if specifying actual depth of search, or 1 if specifying ++ * raw values to write to the register. ++ */ ++extern void ++falcon_nic_set_rx_filter_search_limits(struct efhw_nic *nic, ++ struct efhw_filter_search_limits *lim, ++ int use_raw_values); ++ ++ ++/*! Legacy RX IP filter search depth control interface */ ++extern void ++falcon_nic_rx_filter_ctl_set(struct efhw_nic *nic, uint32_t tcp_full, ++ uint32_t tcp_wild, ++ uint32_t udp_full, uint32_t udp_wild); ++ ++/*! Legacy RX IP filter search depth control interface */ ++extern void ++falcon_nic_rx_filter_ctl_get(struct efhw_nic *nic, uint32_t *tcp_full, ++ uint32_t *tcp_wild, ++ uint32_t *udp_full, uint32_t *udp_wild); ++ ++#endif /* __CI_EFHW_PUBLIC_H__ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efhw/sysdep.h 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,55 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file provides version-independent Linux kernel API for efhw library. ++ * Only kernels >=2.6.9 are supported. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * Certain parts of the driver were implemented by ++ * Alexandra Kossovsky ++ * OKTET Labs Ltd, Russia, ++ * http://oktetlabs.ru, ++ * by request of Solarflare Communications ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#ifndef __CI_EFHW_SYSDEP_LINUX_H__ ++#define __CI_EFHW_SYSDEP_LINUX_H__ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include /* necessary for etherdevice.h on some kernels */ ++#include ++ ++typedef unsigned long irq_flags_t; ++ ++#define spin_lock_destroy(l_) do {} while (0) ++ ++#endif /* __CI_EFHW_SYSDEP_LINUX_H__ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efrm/buddy.h 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,68 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file provides private API for buddy allocator. This API is not ++ * designed for use outside of SFC resource driver. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * Certain parts of the driver were implemented by ++ * Alexandra Kossovsky ++ * OKTET Labs Ltd, Russia, ++ * http://oktetlabs.ru, ++ * by request of Solarflare Communications ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#ifndef __CI_EFRM_BUDDY_H__ ++#define __CI_EFRM_BUDDY_H__ ++ ++#include ++ ++/*! Comment? */ ++struct efrm_buddy_allocator { ++ struct list_head *free_lists; /* array[order+1] */ ++ struct list_head *links; /* array[1<order; ++} ++ ++int efrm_buddy_ctor(struct efrm_buddy_allocator *b, unsigned order); ++void efrm_buddy_dtor(struct efrm_buddy_allocator *b); ++int efrm_buddy_alloc(struct efrm_buddy_allocator *b, unsigned order); ++void efrm_buddy_free(struct efrm_buddy_allocator *b, unsigned addr, ++ unsigned order); ++ ++ ++#endif /* __CI_EFRM_BUDDY_H__ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efrm/buffer_table.h 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,81 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file provides private buffer table API. This API is not designed ++ * for use outside of SFC resource driver. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * Certain parts of the driver were implemented by ++ * Alexandra Kossovsky ++ * OKTET Labs Ltd, Russia, ++ * http://oktetlabs.ru, ++ * by request of Solarflare Communications ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#ifndef __CI_EFRM_BUFFER_TABLE_H__ ++#define __CI_EFRM_BUFFER_TABLE_H__ ++ ++#include ++ ++/*-------------------------------------------------------------------- ++ * ++ * NIC's buffer table. ++ * ++ *--------------------------------------------------------------------*/ ++ ++/*! Managed interface. */ ++ ++/*! construct a managed buffer table object, allocated over a region of ++ * the NICs buffer table space ++ */ ++extern int efrm_buffer_table_ctor(unsigned low, unsigned high); ++/*! destructor for above */ ++extern void efrm_buffer_table_dtor(void); ++ ++/*! allocate a contiguous region of buffer table space */ ++extern int efrm_buffer_table_alloc(unsigned order, ++ struct efhw_buffer_table_allocation *a); ++ ++ ++/*-------------------------------------------------------------------- ++ * ++ * buffer table operations through the HW independent API ++ * ++ *--------------------------------------------------------------------*/ ++ ++/*! free a previously allocated region of buffer table space */ ++extern void efrm_buffer_table_free(struct efhw_buffer_table_allocation *a); ++ ++/*! commit the update of a buffer table entry to every NIC */ ++extern void efrm_buffer_table_commit(void); ++ ++extern void efrm_buffer_table_set(struct efhw_buffer_table_allocation *, ++ struct efhw_nic *, ++ unsigned i, dma_addr_t dma_addr, int owner); ++ ++ ++#endif /* __CI_EFRM_BUFFER_TABLE_H__ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efrm/debug.h 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,78 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file provides debug-related API for efrm library using Linux kernel ++ * primitives. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * Certain parts of the driver were implemented by ++ * Alexandra Kossovsky ++ * OKTET Labs Ltd, Russia, ++ * http://oktetlabs.ru, ++ * by request of Solarflare Communications ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#ifndef __CI_EFRM_DEBUG_LINUX_H__ ++#define __CI_EFRM_DEBUG_LINUX_H__ ++ ++#define EFRM_PRINTK_PREFIX "[sfc efrm] " ++ ++#define EFRM_PRINTK(level, fmt, ...) \ ++ printk(level EFRM_PRINTK_PREFIX fmt "\n", __VA_ARGS__) ++ ++/* Following macros should be used with non-zero format parameters ++ * due to __VA_ARGS__ limitations. Use "%s" with __func__ if you can't ++ * find better parameters. */ ++#define EFRM_ERR(fmt, ...) EFRM_PRINTK(KERN_ERR, fmt, __VA_ARGS__) ++#define EFRM_WARN(fmt, ...) EFRM_PRINTK(KERN_WARNING, fmt, __VA_ARGS__) ++#define EFRM_NOTICE(fmt, ...) EFRM_PRINTK(KERN_NOTICE, fmt, __VA_ARGS__) ++#if !defined(NDEBUG) ++#define EFRM_TRACE(fmt, ...) EFRM_PRINTK(KERN_DEBUG, fmt, __VA_ARGS__) ++#else ++#define EFRM_TRACE(fmt, ...) ++#endif ++ ++#ifndef NDEBUG ++#define EFRM_ASSERT(cond) BUG_ON((cond) == 0) ++#define _EFRM_ASSERT(cond, file, line) \ ++ do { \ ++ if (unlikely(!(cond))) { \ ++ EFRM_ERR("assertion \"%s\" failed at %s %d", \ ++ #cond, file, line); \ ++ BUG(); \ ++ } \ ++ } while (0) ++ ++#define EFRM_DO_DEBUG(expr) expr ++#define EFRM_VERIFY_EQ(expr, val) EFRM_ASSERT((expr) == (val)) ++#else ++#define EFRM_ASSERT(cond) ++#define EFRM_DO_DEBUG(expr) ++#define EFRM_VERIFY_EQ(expr, val) expr ++#endif ++ ++#endif /* __CI_EFRM_DEBUG_LINUX_H__ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efrm/driver_private.h 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,89 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file provides private API of efrm library to be used from the SFC ++ * resource driver. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * Certain parts of the driver were implemented by ++ * Alexandra Kossovsky ++ * OKTET Labs Ltd, Russia, ++ * http://oktetlabs.ru, ++ * by request of Solarflare Communications ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#ifndef __CI_EFRM_DRIVER_PRIVATE_H__ ++#define __CI_EFRM_DRIVER_PRIVATE_H__ ++ ++#include ++#include ++ ++/*-------------------------------------------------------------------- ++ * ++ * global variables ++ * ++ *--------------------------------------------------------------------*/ ++ ++/* Internal structure for resource driver */ ++extern struct efrm_resource_manager *efrm_rm_table[]; ++ ++/*-------------------------------------------------------------------- ++ * ++ * efrm_nic_table handling ++ * ++ *--------------------------------------------------------------------*/ ++ ++struct efrm_nic; ++ ++extern void efrm_driver_ctor(void); ++extern void efrm_driver_dtor(void); ++extern int efrm_driver_register_nic(struct efrm_nic *, int nic_index, ++ int ifindex); ++extern int efrm_driver_unregister_nic(struct efrm_nic *); ++ ++/*-------------------------------------------------------------------- ++ * ++ * create/destroy resource managers ++ * ++ *--------------------------------------------------------------------*/ ++ ++struct vi_resource_dimensions { ++ unsigned evq_int_min, evq_int_lim; ++ unsigned evq_timer_min, evq_timer_lim; ++ unsigned rxq_min, rxq_lim; ++ unsigned txq_min, txq_lim; ++}; ++ ++/*! Initialise resources */ ++extern int ++efrm_resources_init(const struct vi_resource_dimensions *, ++ int buffer_table_min, int buffer_table_lim); ++ ++/*! Tear down resources */ ++extern void efrm_resources_fini(void); ++ ++#endif /* __CI_EFRM_DRIVER_PRIVATE_H__ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efrm/efrm_client.h 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,32 @@ ++#ifndef __EFRM_CLIENT_H__ ++#define __EFRM_CLIENT_H__ ++ ++ ++struct efrm_client; ++ ++ ++struct efrm_client_callbacks { ++ /* Called before device is reset. Callee may block. */ ++ void (*pre_reset)(struct efrm_client *, void *user_data); ++ void (*stop)(struct efrm_client *, void *user_data); ++ void (*restart)(struct efrm_client *, void *user_data); ++}; ++ ++ ++#define EFRM_IFINDEX_DEFAULT -1 ++ ++ ++/* NB. Callbacks may be invoked even before this returns. */ ++extern int efrm_client_get(int ifindex, struct efrm_client_callbacks *, ++ void *user_data, struct efrm_client **client_out); ++extern void efrm_client_put(struct efrm_client *); ++ ++extern struct efhw_nic *efrm_client_get_nic(struct efrm_client *); ++ ++#if 0 ++/* For each resource type... */ ++extern void efrm_x_resource_resume(struct x_resource *); ++#endif ++ ++ ++#endif /* __EFRM_CLIENT_H__ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efrm/efrm_nic.h 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,26 @@ ++#ifndef __EFRM_NIC_H__ ++#define __EFRM_NIC_H__ ++ ++#include ++ ++ ++struct efrm_nic_per_vi { ++ unsigned long state; ++ struct vi_resource *vi; ++}; ++ ++ ++struct efrm_nic { ++ struct efhw_nic efhw_nic; ++ struct list_head link; ++ struct list_head clients; ++ struct efrm_nic_per_vi *vis; ++}; ++ ++ ++#define efrm_nic(_efhw_nic) \ ++ container_of(_efhw_nic, struct efrm_nic, efhw_nic) ++ ++ ++ ++#endif /* __EFRM_NIC_H__ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efrm/filter.h 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,122 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file provides public API for filter resource. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * Certain parts of the driver were implemented by ++ * Alexandra Kossovsky ++ * OKTET Labs Ltd, Russia, ++ * http://oktetlabs.ru, ++ * by request of Solarflare Communications ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#ifndef __CI_EFRM_FILTER_H__ ++#define __CI_EFRM_FILTER_H__ ++ ++#include ++#include ++ ++ ++struct filter_resource; ++struct vi_resource; ++struct efrm_client; ++ ++ ++/*! ++ * Allocate filter resource. ++ * ++ * \param vi_parent VI resource to use as parent. The function takes ++ * reference to the VI resource on success. ++ * \param frs_out pointer to return the new filter resource ++ * ++ * \return status code; if non-zero, frs_out is unchanged ++ */ ++extern int ++efrm_filter_resource_alloc(struct vi_resource *vi_parent, ++ struct filter_resource **frs_out); ++ ++extern void ++efrm_filter_resource_release(struct filter_resource *); ++ ++ ++extern int efrm_filter_resource_clear(struct filter_resource *frs); ++ ++extern int __efrm_filter_resource_set(struct filter_resource *frs, int type, ++ unsigned saddr_be32, uint16_t sport_be16, ++ unsigned daddr_be32, uint16_t dport_be16); ++ ++static inline int ++efrm_filter_resource_tcp_set(struct filter_resource *frs, ++ unsigned saddr, uint16_t sport, ++ unsigned daddr, uint16_t dport) ++{ ++ int type; ++ ++ EFRM_ASSERT((saddr && sport) || (!saddr && !sport)); ++ ++ type = ++ saddr ? EFHW_IP_FILTER_TYPE_TCP_FULL : ++ EFHW_IP_FILTER_TYPE_TCP_WILDCARD; ++ ++ return __efrm_filter_resource_set(frs, type, ++ saddr, sport, daddr, dport); ++} ++ ++static inline int ++efrm_filter_resource_udp_set(struct filter_resource *frs, ++ unsigned saddr, uint16_t sport, ++ unsigned daddr, uint16_t dport) ++{ ++ int type; ++ ++ EFRM_ASSERT((saddr && sport) || (!saddr && !sport)); ++ ++ type = ++ saddr ? EFHW_IP_FILTER_TYPE_UDP_FULL : ++ EFHW_IP_FILTER_TYPE_UDP_WILDCARD; ++ ++ return __efrm_filter_resource_set(frs, ++ type, saddr, sport, daddr, dport); ++} ++ ++ ++extern int ++efrm_filter_resource_instance(struct filter_resource *); ++ ++extern struct efrm_resource * ++efrm_filter_resource_to_resource(struct filter_resource *); ++ ++extern struct filter_resource * ++efrm_filter_resource_from_resource(struct efrm_resource *); ++ ++extern void ++efrm_filter_resource_free(struct filter_resource *); ++ ++ ++#endif /* __CI_EFRM_FILTER_H__ */ ++/*! \cidoxg_end */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efrm/iobufset.h 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,110 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file provides public API for iobufset resource. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * Certain parts of the driver were implemented by ++ * Alexandra Kossovsky ++ * OKTET Labs Ltd, Russia, ++ * http://oktetlabs.ru, ++ * by request of Solarflare Communications ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#ifndef __CI_EFRM_IOBUFSET_H__ ++#define __CI_EFRM_IOBUFSET_H__ ++ ++#include ++ ++/*! Iobufset resource structture. ++ * Users should not access the structure fields directly, but use the API ++ * below. ++ * However, this structure should not be moved out of public headers, ++ * because part of API (ex. efrm_iobufset_dma_addr function) is inline and ++ * is used in the fast-path code. ++ */ ++struct iobufset_resource { ++ struct efrm_resource rs; ++ struct vi_resource *evq; ++ struct iobufset_resource *linked; ++ struct efhw_buffer_table_allocation buf_tbl_alloc; ++ unsigned int n_bufs; ++ unsigned int pages_per_contiguous_chunk; ++ unsigned chunk_order; ++ struct efhw_iopage bufs[1]; ++ /*!< up to n_bufs can follow this, so this must be the last member */ ++}; ++ ++#define iobufset_resource(rs1) \ ++ container_of((rs1), struct iobufset_resource, rs) ++ ++/*! ++ * Allocate iobufset resource. ++ * ++ * \param vi VI that "owns" these buffers. Grabs a reference ++ * on success. ++ * \param linked Uses memory from an existing iobufset. Grabs a ++ * reference on success. ++ * \param iobrs_out pointer to return the new filter resource ++ * ++ * \return status code; if non-zero, frs_out is unchanged ++ */ ++extern int ++efrm_iobufset_resource_alloc(int32_t n_pages, ++ int32_t pages_per_contiguous_chunk, ++ struct vi_resource *vi, ++ struct iobufset_resource *linked, ++ bool phys_addr_mode, ++ struct iobufset_resource **iobrs_out); ++ ++extern void efrm_iobufset_resource_free(struct iobufset_resource *); ++extern void efrm_iobufset_resource_release(struct iobufset_resource *); ++ ++static inline char * ++efrm_iobufset_ptr(struct iobufset_resource *rs, unsigned offs) ++{ ++ EFRM_ASSERT(offs < (unsigned)(rs->n_bufs << PAGE_SHIFT)); ++ return efhw_iopage_ptr(&rs->bufs[offs >> PAGE_SHIFT]) ++ + (offs & (PAGE_SIZE - 1)); ++} ++ ++static inline char *efrm_iobufset_page_ptr(struct iobufset_resource *rs, ++ unsigned page_i) ++{ ++ EFRM_ASSERT(page_i < (unsigned)rs->n_bufs); ++ return efhw_iopage_ptr(&rs->bufs[page_i]); ++} ++ ++static inline dma_addr_t ++efrm_iobufset_dma_addr(struct iobufset_resource *rs, unsigned offs) ++{ ++ EFRM_ASSERT(offs < (unsigned)(rs->n_bufs << PAGE_SHIFT)); ++ return efhw_iopage_dma_addr(&rs->bufs[offs >> PAGE_SHIFT]) ++ + (offs & (PAGE_SIZE - 1)); ++} ++ ++#endif /* __CI_EFRM_IOBUFSET_H__ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efrm/nic_set.h 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,104 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file provides public API for NIC sets. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * Certain parts of the driver were implemented by ++ * Alexandra Kossovsky ++ * OKTET Labs Ltd, Russia, ++ * http://oktetlabs.ru, ++ * by request of Solarflare Communications ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#ifndef __CI_EFRM_NIC_SET_H__ ++#define __CI_EFRM_NIC_SET_H__ ++ ++#include ++#include ++#include ++ ++/*-------------------------------------------------------------------- ++ * ++ * efrm_nic_set_t - tracks which NICs something has been done on ++ * ++ *--------------------------------------------------------------------*/ ++ ++/* Internal suructure of efrm_nic_set_t should not be referenced outside of ++ * this file. Add a new accessor if you should do it. */ ++typedef struct { ++ uint32_t nics; ++} efrm_nic_set_t; ++ ++#if EFHW_MAX_NR_DEVS > 32 ++#error change efrm_nic_set to handle EFHW_MAX_NR_DEVS number of devices ++#endif ++ ++static inline bool ++efrm_nic_set_read(const efrm_nic_set_t *nic_set, unsigned index) ++{ ++ EFRM_ASSERT(nic_set); ++ EFRM_ASSERT(index < EFHW_MAX_NR_DEVS && index < 32); ++ return (nic_set->nics & (1 << index)) ? true : false; ++} ++ ++static inline void ++efrm_nic_set_write(efrm_nic_set_t *nic_set, unsigned index, bool value) ++{ ++ EFRM_ASSERT(nic_set); ++ EFRM_ASSERT(index < EFHW_MAX_NR_DEVS && index < 32); ++ EFRM_ASSERT(value == false || value == true); ++ nic_set->nics = (nic_set->nics & (~(1 << index))) + (value << index); ++} ++ ++static inline void efrm_nic_set_clear(efrm_nic_set_t *nic_set) ++{ ++ nic_set->nics = 0; ++} ++ ++static inline void efrm_nic_set_all(efrm_nic_set_t *nic_set) ++{ ++ nic_set->nics = 0xffffffff; ++} ++ ++static inline bool efrm_nic_set_is_all_clear(efrm_nic_set_t *nic_set) ++{ ++ return nic_set->nics == 0 ? true : false; ++} ++ ++#define EFRM_NIC_SET_FMT "%x" ++ ++static inline uint32_t efrm_nic_set_pri_arg(efrm_nic_set_t *nic_set) ++{ ++ return nic_set->nics; ++} ++ ++#define EFRM_FOR_EACH_NIC_INDEX_IN_SET(_set, _nic_i) \ ++ for ((_nic_i) = 0; (_nic_i) < EFHW_MAX_NR_DEVS; ++(_nic_i)) \ ++ if (efrm_nic_set_read((_set), (_nic_i))) ++ ++#endif /* __CI_EFRM_NIC_SET_H__ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efrm/nic_table.h 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,98 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file provides public API for NIC table. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * Certain parts of the driver were implemented by ++ * Alexandra Kossovsky ++ * OKTET Labs Ltd, Russia, ++ * http://oktetlabs.ru, ++ * by request of Solarflare Communications ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#ifndef __CI_EFRM_NIC_TABLE_H__ ++#define __CI_EFRM_NIC_TABLE_H__ ++ ++#include ++#include ++ ++/*-------------------------------------------------------------------- ++ * ++ * struct efrm_nic_table - top level driver object keeping all NICs - ++ * implemented in driver_object.c ++ * ++ *--------------------------------------------------------------------*/ ++ ++/*! Comment? */ ++struct efrm_nic_table { ++ /*! nics attached to this driver */ ++ struct efhw_nic *nic[EFHW_MAX_NR_DEVS]; ++ /*! pointer to an arbitrary struct efhw_nic if one exists; ++ * for code which does not care which NIC it wants but ++ * still needs one. Note you cannot assume nic[0] exists. */ ++ struct efhw_nic *a_nic; ++ uint32_t nic_count; /*!< number of nics attached to this driver */ ++ spinlock_t lock; /*!< lock for table modifications */ ++ atomic_t ref_count; /*!< refcount for users of nic table */ ++}; ++ ++/* Resource driver structures used by other drivers as well */ ++extern struct efrm_nic_table *efrm_nic_tablep; ++ ++static inline void efrm_nic_table_hold(void) ++{ ++ atomic_inc(&efrm_nic_tablep->ref_count); ++} ++ ++static inline void efrm_nic_table_rele(void) ++{ ++ atomic_dec(&efrm_nic_tablep->ref_count); ++} ++ ++static inline int efrm_nic_table_held(void) ++{ ++ return atomic_read(&efrm_nic_tablep->ref_count) != 0; ++} ++ ++/* Run code block _x multiple times with variable nic set to each ++ * registered NIC in turn. ++ * DO NOT "break" out of this loop early. */ ++#define EFRM_FOR_EACH_NIC(_nic_i, _nic) \ ++ for ((_nic_i) = (efrm_nic_table_hold(), 0); \ ++ (_nic_i) < EFHW_MAX_NR_DEVS || (efrm_nic_table_rele(), 0); \ ++ (_nic_i)++) \ ++ if (((_nic) = efrm_nic_tablep->nic[_nic_i])) ++ ++#define EFRM_FOR_EACH_NIC_IN_SET(_set, _i, _nic) \ ++ for ((_i) = (efrm_nic_table_hold(), 0); \ ++ (_i) < EFHW_MAX_NR_DEVS || (efrm_nic_table_rele(), 0); \ ++ ++(_i)) \ ++ if (((_nic) = efrm_nic_tablep->nic[_i]) && \ ++ efrm_nic_set_read((_set), (_i))) ++ ++#endif /* __CI_EFRM_NIC_TABLE_H__ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efrm/private.h 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,118 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file provides private API of efrm library -- resource handling. ++ * This API is not designed for use outside of SFC resource driver. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * Certain parts of the driver were implemented by ++ * Alexandra Kossovsky ++ * OKTET Labs Ltd, Russia, ++ * http://oktetlabs.ru, ++ * by request of Solarflare Communications ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#ifndef __CI_EFRM_PRIVATE_H__ ++#define __CI_EFRM_PRIVATE_H__ ++ ++#include ++#include ++#include ++#include ++ ++/*-------------------------------------------------------------------- ++ * ++ * create resource managers ++ * ++ *--------------------------------------------------------------------*/ ++ ++/*! Create a resource manager for various types of resources ++ */ ++extern int ++efrm_create_iobufset_resource_manager(struct efrm_resource_manager **out); ++ ++extern int ++efrm_create_filter_resource_manager(struct efrm_resource_manager **out); ++ ++extern int ++efrm_create_vi_resource_manager(struct efrm_resource_manager **out, ++ const struct vi_resource_dimensions *); ++ ++ ++/*-------------------------------------------------------------------- ++ * ++ * Instance pool management ++ * ++ *--------------------------------------------------------------------*/ ++ ++/*! Allocate instance pool. Use kfifo_vfree to destroy it. */ ++static inline int ++efrm_kfifo_id_ctor(struct kfifo **ids_out, ++ unsigned int base, unsigned int limit, spinlock_t *lock) ++{ ++ unsigned int i; ++ struct kfifo *ids; ++ unsigned char *buffer; ++ unsigned int size = roundup_pow_of_two((limit - base) * sizeof(int)); ++ EFRM_ASSERT(base <= limit); ++ buffer = vmalloc(size); ++ ids = kfifo_init(buffer, size, GFP_KERNEL, lock); ++ if (IS_ERR(ids)) ++ return PTR_ERR(ids); ++ for (i = base; i < limit; i++) ++ EFRM_VERIFY_EQ(__kfifo_put(ids, (unsigned char *)&i, ++ sizeof(i)), sizeof(i)); ++ ++ *ids_out = ids; ++ return 0; ++} ++ ++/*-------------------------------------------------------------------- ++ * ++ * Various private functions ++ * ++ *--------------------------------------------------------------------*/ ++ ++/*! Initialize the fields in the provided resource manager memory area ++ * \param rm The area of memory to be initialized ++ * \param dtor A method to destroy the resource manager ++ * \param name A Textual name for the resource manager ++ * \param type The type of resource managed ++ * \param initial_table_size Initial size of the ID table ++ * \param auto_destroy Destroy resource manager on driver onload iff true ++ * ++ * A default table size is provided if the value 0 is provided. ++ */ ++extern int ++efrm_resource_manager_ctor(struct efrm_resource_manager *rm, ++ void (*dtor)(struct efrm_resource_manager *), ++ const char *name, unsigned type); ++ ++extern void efrm_resource_manager_dtor(struct efrm_resource_manager *rm); ++ ++ ++#endif /* __CI_EFRM_PRIVATE_H__ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efrm/resource.h 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,119 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file provides public interface of efrm library -- resource handling. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * Certain parts of the driver were implemented by ++ * Alexandra Kossovsky ++ * OKTET Labs Ltd, Russia, ++ * http://oktetlabs.ru, ++ * by request of Solarflare Communications ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#ifndef __CI_EFRM_RESOURCE_H__ ++#define __CI_EFRM_RESOURCE_H__ ++ ++/*-------------------------------------------------------------------- ++ * ++ * headers for type dependencies ++ * ++ *--------------------------------------------------------------------*/ ++ ++#include ++#include ++#include ++#include ++ ++#ifndef __ci_driver__ ++#error "Driver-only file" ++#endif ++ ++/*-------------------------------------------------------------------- ++ * ++ * struct efrm_resource - represents an allocated resource ++ * (eg. pinned pages of memory, or resource on a NIC) ++ * ++ *--------------------------------------------------------------------*/ ++ ++/*! Representation of an allocated resource */ ++struct efrm_resource { ++ int rs_ref_count; ++ efrm_resource_handle_t rs_handle; ++ struct efrm_client *rs_client; ++ struct list_head rs_client_link; ++ struct list_head rs_manager_link; ++}; ++ ++/*-------------------------------------------------------------------- ++ * ++ * managed resource abstraction ++ * ++ *--------------------------------------------------------------------*/ ++ ++/*! Factory for resources of a specific type */ ++struct efrm_resource_manager { ++ const char *rm_name; /*!< human readable only */ ++ spinlock_t rm_lock; ++#ifndef NDEBUG ++ unsigned rm_type; ++#endif ++ int rm_resources; ++ int rm_resources_hiwat; ++ struct list_head rm_resources_list; ++ /** ++ * Destructor for the resource manager. Other resource managers ++ * might be already dead, although the system guarantees that ++ * managers are destructed in the order by which they were created ++ */ ++ void (*rm_dtor)(struct efrm_resource_manager *); ++}; ++ ++#ifdef NDEBUG ++# define EFRM_RESOURCE_ASSERT_VALID(rs, rc_mbz) ++# define EFRM_RESOURCE_MANAGER_ASSERT_VALID(rm) ++#else ++/*! Check validity of resource and report on failure */ ++extern void efrm_resource_assert_valid(struct efrm_resource *, ++ int rc_may_be_zero, ++ const char *file, int line); ++# define EFRM_RESOURCE_ASSERT_VALID(rs, rc_mbz) \ ++ efrm_resource_assert_valid((rs), (rc_mbz), __FILE__, __LINE__) ++ ++/*! Check validity of resource manager and report on failure */ ++extern void efrm_resource_manager_assert_valid(struct efrm_resource_manager *, ++ const char *file, int line); ++# define EFRM_RESOURCE_MANAGER_ASSERT_VALID(rm) \ ++ efrm_resource_manager_assert_valid((rm), __FILE__, __LINE__) ++#endif ++ ++ ++extern void efrm_resource_ref(struct efrm_resource *rs); ++extern int __efrm_resource_release(struct efrm_resource *); ++ ++ ++#endif /* __CI_EFRM_RESOURCE_H__ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efrm/resource_id.h 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,104 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file provides public type and definitions resource handle, and the ++ * definitions of resource types. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#ifndef __CI_DRIVER_EFRM_RESOURCE_ID_H__ ++#define __CI_DRIVER_EFRM_RESOURCE_ID_H__ ++ ++/*********************************************************************** ++ * Resource handles ++ * ++ * Resource handles are intended for identifying resources at kernel ++ * level, within the context of a particular NIC. particularly because ++ * for some resource types, the low 16 bites correspond to hardware ++ * IDs. They were historically also used at user level, with a nonce ++ * stored in the bits 16 to 27 (inclusive), but that approach is ++ * deprecated (but sill alive!). ++ * ++ * The handle value 0 is used to mean "no resource". ++ * Identify resources within the context of a file descriptor at user ++ * level. ++ ***********************************************************************/ ++ ++typedef struct { ++ uint32_t handle; ++} efrm_resource_handle_t; ++ ++/* You may think these following functions should all have ++ * _HANDLE_ in their names, but really we are providing an abstract set ++ * of methods on a (hypothetical) efrm_resource_t object, with ++ * efrm_resource_handle_t being just the reference one holds to access ++ * the object (aka "this" or "self"). ++ */ ++ ++/* Below I use inline instead of macros where possible in order to get ++ * more type checking help from the compiler; hopefully we'll never ++ * have to rewrite these to use #define as we've found some horrible ++ * compiler on which we cannot make static inline do the Right Thing (tm). ++ * ++ * For consistency and to avoid pointless change I spell these ++ * routines as macro names (CAPTILIZE_UNDERSCORED), which also serves ++ * to remind people they are compact and inlined. ++ */ ++ ++#define EFRM_RESOURCE_FMT "[rs:%08x]" ++ ++static inline unsigned EFRM_RESOURCE_PRI_ARG(efrm_resource_handle_t h) ++{ ++ return h.handle; ++} ++ ++static inline unsigned EFRM_RESOURCE_INSTANCE(efrm_resource_handle_t h) ++{ ++ return h.handle & 0x0000ffff; ++} ++ ++static inline unsigned EFRM_RESOURCE_TYPE(efrm_resource_handle_t h) ++{ ++ return (h.handle & 0xf0000000) >> 28; ++} ++ ++/*********************************************************************** ++ * Resource type codes ++ ***********************************************************************/ ++ ++#define EFRM_RESOURCE_IOBUFSET 0x0 ++#define EFRM_RESOURCE_VI 0x1 ++#define EFRM_RESOURCE_FILTER 0x2 ++#define EFRM_RESOURCE_NUM 0x3 /* This isn't a resource! */ ++ ++#define EFRM_RESOURCE_NAME(type) \ ++ ((type) == EFRM_RESOURCE_IOBUFSET? "IOBUFSET" : \ ++ (type) == EFRM_RESOURCE_VI? "VI" : \ ++ (type) == EFRM_RESOURCE_FILTER? "FILTER" : \ ++ "") ++ ++#endif /* __CI_DRIVER_EFRM_RESOURCE_ID_H__ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efrm/sysdep.h 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,46 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file provides Linux-like system-independent API for efrm library. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * Certain parts of the driver were implemented by ++ * Alexandra Kossovsky ++ * OKTET Labs Ltd, Russia, ++ * http://oktetlabs.ru, ++ * by request of Solarflare Communications ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#ifndef __CI_EFRM_SYSDEP_H__ ++#define __CI_EFRM_SYSDEP_H__ ++ ++/* Spinlocks are defined in efhw/sysdep.h */ ++#include ++ ++#include ++ ++#endif /* __CI_EFRM_SYSDEP_H__ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efrm/sysdep_linux.h 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,93 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file provides version-independent Linux kernel API for efrm library. ++ * Only kernels >=2.6.9 are supported. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Kfifo API is partially stolen from linux-2.6.22/include/linux/list.h ++ * Copyright (C) 2004 Stelian Pop ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * Certain parts of the driver were implemented by ++ * Alexandra Kossovsky ++ * OKTET Labs Ltd, Russia, ++ * http://oktetlabs.ru, ++ * by request of Solarflare Communications ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#ifndef __CI_EFRM_SYSDEP_LINUX_H__ ++#define __CI_EFRM_SYSDEP_LINUX_H__ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++/******************************************************************** ++ * ++ * List API ++ * ++ ********************************************************************/ ++ ++static inline struct list_head *list_pop(struct list_head *list) ++{ ++ struct list_head *link = list->next; ++ list_del(link); ++ return link; ++} ++ ++static inline struct list_head *list_pop_tail(struct list_head *list) ++{ ++ struct list_head *link = list->prev; ++ list_del(link); ++ return link; ++} ++ ++/******************************************************************** ++ * ++ * Kfifo API ++ * ++ ********************************************************************/ ++ ++static inline void kfifo_vfree(struct kfifo *fifo) ++{ ++ vfree(fifo->buffer); ++ kfree(fifo); ++} ++ ++#endif /* __CI_EFRM_SYSDEP_LINUX_H__ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efrm/vi_resource.h 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,157 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file contains public API for VI resource. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * Certain parts of the driver were implemented by ++ * Alexandra Kossovsky ++ * OKTET Labs Ltd, Russia, ++ * http://oktetlabs.ru, ++ * by request of Solarflare Communications ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#ifndef __CI_EFRM_VI_RESOURCE_H__ ++#define __CI_EFRM_VI_RESOURCE_H__ ++ ++#include ++#include ++#include ++ ++struct vi_resource; ++ ++/* Make these inline instead of macros for type checking */ ++static inline struct vi_resource * ++efrm_to_vi_resource(struct efrm_resource *rs) ++{ ++ EFRM_ASSERT(EFRM_RESOURCE_TYPE(rs->rs_handle) == EFRM_RESOURCE_VI); ++ return (struct vi_resource *) rs; ++} ++static inline struct ++efrm_resource *efrm_from_vi_resource(struct vi_resource *rs) ++{ ++ return (struct efrm_resource *)rs; ++} ++ ++#define EFAB_VI_RESOURCE_INSTANCE(virs) \ ++ EFRM_RESOURCE_INSTANCE(efrm_from_vi_resource(virs)->rs_handle) ++ ++#define EFAB_VI_RESOURCE_PRI_ARG(virs) \ ++ EFRM_RESOURCE_PRI_ARG(efrm_from_vi_resource(virs)->rs_handle) ++ ++extern int ++efrm_vi_resource_alloc(struct efrm_client *client, ++ struct vi_resource *evq_virs, ++ uint16_t vi_flags, int32_t evq_capacity, ++ int32_t txq_capacity, int32_t rxq_capacity, ++ uint8_t tx_q_tag, uint8_t rx_q_tag, ++ struct vi_resource **virs_in_out, ++ uint32_t *out_io_mmap_bytes, ++ uint32_t *out_mem_mmap_bytes, ++ uint32_t *out_txq_capacity, ++ uint32_t *out_rxq_capacity); ++ ++extern void efrm_vi_resource_free(struct vi_resource *); ++extern void efrm_vi_resource_release(struct vi_resource *); ++ ++ ++/*-------------------------------------------------------------------- ++ * ++ * eventq handling ++ * ++ *--------------------------------------------------------------------*/ ++ ++/*! Reset an event queue and clear any associated timers */ ++extern void efrm_eventq_reset(struct vi_resource *virs); ++ ++/*! Register a kernel-level handler for the event queue. This function is ++ * called whenever a timer expires, or whenever the event queue is woken ++ * but no thread is blocked on it. ++ * ++ * This function returns -EBUSY if a callback is already installed. ++ * ++ * \param rs Event-queue resource ++ * \param handler Callback-handler ++ * \param arg Argument to pass to callback-handler ++ * \return Status code ++ */ ++extern int ++efrm_eventq_register_callback(struct vi_resource *rs, ++ void (*handler)(void *arg, int is_timeout, ++ struct efhw_nic *nic), ++ void *arg); ++ ++/*! Kill the kernel-level callback. ++ * ++ * This function stops the timer from running and unregisters the callback ++ * function. It waits for any running timeout handlers to complete before ++ * returning. ++ * ++ * \param rs Event-queue resource ++ * \return Nothing ++ */ ++extern void efrm_eventq_kill_callback(struct vi_resource *rs); ++ ++/*! Ask the NIC to generate a wakeup when an event is next delivered. */ ++extern void efrm_eventq_request_wakeup(struct vi_resource *rs, ++ unsigned current_ptr); ++ ++/*! Register a kernel-level handler for flush completions. ++ * \TODO Currently, it is unsafe to install a callback more than once. ++ * ++ * \param rs VI resource being flushed. ++ * \param handler Callback handler function. ++ * \param arg Argument to be passed to handler. ++ */ ++extern void ++efrm_vi_register_flush_callback(struct vi_resource *rs, ++ void (*handler)(void *), ++ void *arg); ++ ++int efrm_vi_resource_flush_retry(struct vi_resource *virs); ++ ++/*! Comment? */ ++extern int efrm_pt_flush(struct vi_resource *); ++ ++/*! Comment? */ ++extern int efrm_pt_pace(struct vi_resource *, unsigned int val); ++ ++uint32_t efrm_vi_rm_txq_bytes(struct vi_resource *virs ++ /*,struct efhw_nic *nic */); ++uint32_t efrm_vi_rm_rxq_bytes(struct vi_resource *virs ++ /*,struct efhw_nic *nic */); ++uint32_t efrm_vi_rm_evq_bytes(struct vi_resource *virs ++ /*,struct efhw_nic *nic */); ++ ++ ++/* Fill [out_vi_data] with information required to allow a VI to be init'd. ++ * [out_vi_data] must ref at least VI_MAPPINGS_SIZE bytes. ++ */ ++extern void efrm_vi_resource_mappings(struct vi_resource *, void *out_vi_data); ++ ++ ++#endif /* __CI_EFRM_VI_RESOURCE_H__ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efrm/vi_resource_manager.h 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,155 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file contains type definitions for VI resource. These types ++ * may be used outside of the SFC resource driver, but such use is not ++ * recommended. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#ifndef __CI_DRIVER_EFAB_VI_RESOURCE_MANAGER_H__ ++#define __CI_DRIVER_EFAB_VI_RESOURCE_MANAGER_H__ ++ ++#include ++#include ++ ++ ++#define EFRM_VI_RM_DMA_QUEUE_COUNT 2 ++#define EFRM_VI_RM_DMA_QUEUE_TX 0 ++#define EFRM_VI_RM_DMA_QUEUE_RX 1 ++ ++/** Numbers of bits which can be set in the evq_state member of ++ * vi_resource_evq_info. */ ++enum { ++ /** This bit is set if a wakeup has been requested on the NIC. */ ++ VI_RESOURCE_EVQ_STATE_WAKEUP_PENDING, ++ /** This bit is set if the wakeup is valid for the sleeping ++ * process. */ ++ VI_RESOURCE_EVQ_STATE_CALLBACK_REGISTERED, ++ /** This bit is set if a wakeup or timeout event is currently being ++ * processed. */ ++ VI_RESOURCE_EVQ_STATE_BUSY, ++}; ++#define VI_RESOURCE_EVQ_STATE(X) \ ++ (((int32_t)1) << (VI_RESOURCE_EVQ_STATE_##X)) ++ ++ ++/*! Global information for the VI resource manager. */ ++struct vi_resource_manager { ++ struct efrm_resource_manager rm; ++ ++ struct kfifo *instances_with_timer; ++ int with_timer_base; ++ int with_timer_limit; ++ struct kfifo *instances_with_interrupt; ++ int with_interrupt_base; ++ int with_interrupt_limit; ++ ++ bool iscsi_dmaq_instance_is_free; ++ ++ /* We keep VI resources which need flushing on these lists. The VI ++ * is put on the outstanding list when the flush request is issued ++ * to the hardware and removed when the flush event arrives. The ++ * hardware can only handle a limited number of RX flush requests at ++ * once, so VIs are placed in the waiting list until the flush can ++ * be issued. Flushes can be requested by the client or internally ++ * by the VI resource manager. In the former case, the reference ++ * count must be non-zero for the duration of the flush and in the ++ * later case, the reference count must be zero. */ ++ struct list_head rx_flush_waiting_list; ++ struct list_head rx_flush_outstanding_list; ++ struct list_head tx_flush_outstanding_list; ++ int rx_flush_outstanding_count; ++ ++ /* once the flush has happened we push the close into the work queue ++ * so its OK on Windows to free the resources (Bug 3469). Resources ++ * on this list have zero reference count. ++ */ ++ struct list_head close_pending; ++ struct work_struct work_item; ++ struct workqueue_struct *workqueue; ++}; ++ ++struct vi_resource_nic_info { ++ struct eventq_resource_hardware evq_pages; ++ struct efhw_iopages dmaq_pages[EFRM_VI_RM_DMA_QUEUE_COUNT]; ++}; ++ ++struct vi_resource { ++ /* Some macros make the assumption that the struct efrm_resource is ++ * the first member of a struct vi_resource. */ ++ struct efrm_resource rs; ++ atomic_t evq_refs; /*!< Number of users of the event queue. */ ++ ++ uint32_t bar_mmap_bytes; ++ uint32_t mem_mmap_bytes; ++ ++ int32_t evq_capacity; ++ int32_t dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_COUNT]; ++ ++ uint8_t dmaq_tag[EFRM_VI_RM_DMA_QUEUE_COUNT]; ++ uint16_t flags; ++ ++ /* we keep PT endpoints that have been destroyed on a list ++ * until we have seen their TX and RX DMAQs flush complete ++ * (see Bug 1217) ++ */ ++ struct list_head rx_flush_link; ++ struct list_head tx_flush_link; ++ int rx_flushing; ++ int rx_flush_outstanding; ++ int tx_flushing; ++ uint64_t flush_time; ++ int flush_count; ++ ++ void (*flush_callback_fn)(void *); ++ void *flush_callback_arg; ++ ++ void (*evq_callback_fn) (void *arg, int is_timeout, ++ struct efhw_nic *nic); ++ void *evq_callback_arg; ++ ++ struct vi_resource *evq_virs; /*!< EVQ for DMA queues */ ++ ++ struct efhw_buffer_table_allocation ++ dmaq_buf_tbl_alloc[EFRM_VI_RM_DMA_QUEUE_COUNT]; ++ ++ struct vi_resource_nic_info nic_info; ++}; ++ ++#undef vi_resource ++#define vi_resource(rs1) container_of((rs1), struct vi_resource, rs) ++ ++static inline dma_addr_t ++efrm_eventq_dma_addr(struct vi_resource *virs) ++{ ++ struct eventq_resource_hardware *hw; ++ hw = &virs->nic_info.evq_pages; ++ return efhw_iopages_dma_addr(&hw->iobuff) + hw->iobuff_off; ++} ++ ++#endif /* __CI_DRIVER_EFAB_VI_RESOURCE_MANAGER_H__ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/ci/efrm/vi_resource_private.h 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,65 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file contains private API for VI resource. The API is not designed ++ * to be used outside of the SFC resource driver. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#ifndef __CI_EFRM_VI_RESOURCE_PRIVATE_H__ ++#define __CI_EFRM_VI_RESOURCE_PRIVATE_H__ ++ ++#include ++#include ++ ++extern struct vi_resource_manager *efrm_vi_manager; ++ ++/*************************************************************************/ ++ ++extern void efrm_vi_rm_delayed_free(struct work_struct *data); ++ ++extern void efrm_vi_rm_salvage_flushed_vis(void); ++ ++void efrm_vi_rm_free_flushed_resource(struct vi_resource *virs); ++ ++void efrm_vi_rm_init_dmaq(struct vi_resource *virs, int queue_index, ++ struct efhw_nic *nic); ++ ++/*! Wakeup handler */ ++extern void efrm_handle_wakeup_event(struct efhw_nic *nic, unsigned id); ++ ++/*! Timeout handler */ ++extern void efrm_handle_timeout_event(struct efhw_nic *nic, unsigned id); ++ ++/*! DMA flush handler */ ++extern void efrm_handle_dmaq_flushed(struct efhw_nic *nic, unsigned id, ++ int rx_flush); ++ ++/*! SRAM update handler */ ++extern void efrm_handle_sram_event(struct efhw_nic *nic); ++ ++#endif /* __CI_EFRM_VI_RESOURCE_PRIVATE_H__ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/driver_object.c 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,328 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file contains support for the global driver variables. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * Certain parts of the driver were implemented by ++ * Alexandra Kossovsky ++ * OKTET Labs Ltd, Russia, ++ * http://oktetlabs.ru, ++ * by request of Solarflare Communications ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include "efrm_internal.h" ++ ++/* We use #define rather than static inline here so that the Windows ++ * "prefast" compiler can see its own locking primitive when these ++ * two function are used (and then perform extra checking where they ++ * are used) ++ * ++ * Both macros operate on an irq_flags_t ++*/ ++ ++#define efrm_driver_lock(irqlock_state) \ ++ spin_lock_irqsave(&efrm_nic_tablep->lock, irqlock_state) ++ ++#define efrm_driver_unlock(irqlock_state) \ ++ spin_unlock_irqrestore(&efrm_nic_tablep->lock, \ ++ irqlock_state); ++ ++/* These routines are all methods on the architecturally singleton ++ global variables: efrm_nic_table, efrm_rm_table. ++ ++ I hope we never find a driver model that does not allow global ++ structure variables :) (but that would break almost every driver I've ++ ever seen). ++*/ ++ ++/*! Exported driver state */ ++static struct efrm_nic_table efrm_nic_table; ++struct efrm_nic_table *efrm_nic_tablep; ++EXPORT_SYMBOL(efrm_nic_tablep); ++ ++ ++/* Internal table with resource managers. ++ * We'd like to not export it, but we are still using efrm_rm_table ++ * in the char driver. So, it is declared in the private header with ++ * a purpose. */ ++struct efrm_resource_manager *efrm_rm_table[EFRM_RESOURCE_NUM]; ++EXPORT_SYMBOL(efrm_rm_table); ++ ++ ++/* List of registered nics. */ ++static LIST_HEAD(efrm_nics); ++ ++ ++void efrm_driver_ctor(void) ++{ ++ efrm_nic_tablep = &efrm_nic_table; ++ spin_lock_init(&efrm_nic_tablep->lock); ++ EFRM_TRACE("%s: driver created", __func__); ++} ++ ++void efrm_driver_dtor(void) ++{ ++ EFRM_ASSERT(!efrm_nic_table_held()); ++ ++ spin_lock_destroy(&efrm_nic_tablep->lock); ++ memset(&efrm_nic_table, 0, sizeof(efrm_nic_table)); ++ memset(&efrm_rm_table, 0, sizeof(efrm_rm_table)); ++ EFRM_TRACE("%s: driver deleted", __func__); ++} ++ ++int efrm_driver_register_nic(struct efrm_nic *rnic, int nic_index, ++ int ifindex) ++{ ++ struct efhw_nic *nic = &rnic->efhw_nic; ++ struct efrm_nic_per_vi *vis; ++ int max_vis, rc = 0; ++ irq_flags_t lock_flags; ++ ++ EFRM_ASSERT(nic_index >= 0); ++ EFRM_ASSERT(ifindex >= 0); ++ ++ max_vis = 4096; /* TODO: Get runtime value. */ ++ vis = vmalloc(max_vis * sizeof(rnic->vis[0])); ++ if (vis == NULL) { ++ EFRM_ERR("%s: Out of memory", __func__); ++ return -ENOMEM; ++ } ++ ++ efrm_driver_lock(lock_flags); ++ ++ if (efrm_nic_table_held()) { ++ EFRM_ERR("%s: driver object is in use", __func__); ++ rc = -EBUSY; ++ goto done; ++ } ++ ++ if (efrm_nic_tablep->nic_count == EFHW_MAX_NR_DEVS) { ++ EFRM_ERR("%s: filled up NIC table size %d", __func__, ++ EFHW_MAX_NR_DEVS); ++ rc = -E2BIG; ++ goto done; ++ } ++ ++ rnic->vis = vis; ++ ++ EFRM_ASSERT(efrm_nic_tablep->nic[nic_index] == NULL); ++ efrm_nic_tablep->nic[nic_index] = nic; ++ nic->index = nic_index; ++ nic->ifindex = ifindex; ++ ++ if (efrm_nic_tablep->a_nic == NULL) ++ efrm_nic_tablep->a_nic = nic; ++ ++ efrm_nic_tablep->nic_count++; ++ ++ INIT_LIST_HEAD(&rnic->clients); ++ list_add(&rnic->link, &efrm_nics); ++ ++ efrm_driver_unlock(lock_flags); ++ return 0; ++ ++done: ++ efrm_driver_unlock(lock_flags); ++ vfree(vis); ++ return rc; ++} ++ ++int efrm_driver_unregister_nic(struct efrm_nic *rnic) ++{ ++ struct efhw_nic *nic = &rnic->efhw_nic; ++ int rc = 0; ++ int nic_index = nic->index; ++ irq_flags_t lock_flags; ++ ++ EFRM_ASSERT(nic_index >= 0); ++ ++ efrm_driver_lock(lock_flags); ++ ++ if (efrm_nic_table_held()) { ++ EFRM_ERR("%s: driver object is in use", __func__); ++ rc = -EBUSY; ++ goto done; ++ } ++ if (!list_empty(&rnic->clients)) { ++ EFRM_ERR("%s: nic has active clients", __func__); ++ rc = -EBUSY; ++ goto done; ++ } ++ ++ EFRM_ASSERT(efrm_nic_tablep->nic[nic_index] == nic); ++ EFRM_ASSERT(list_empty(&rnic->clients)); ++ ++ list_del(&rnic->link); ++ ++ nic->index = -1; ++ efrm_nic_tablep->nic[nic_index] = NULL; ++ ++ --efrm_nic_tablep->nic_count; ++ ++ if (efrm_nic_tablep->a_nic == nic) { ++ if (efrm_nic_tablep->nic_count == 0) { ++ efrm_nic_tablep->a_nic = NULL; ++ } else { ++ for (nic_index = 0; nic_index < EFHW_MAX_NR_DEVS; ++ nic_index++) { ++ if (efrm_nic_tablep->nic[nic_index] != NULL) ++ efrm_nic_tablep->a_nic = ++ efrm_nic_tablep->nic[nic_index]; ++ } ++ EFRM_ASSERT(efrm_nic_tablep->a_nic); ++ } ++ } ++ ++done: ++ efrm_driver_unlock(lock_flags); ++ return rc; ++} ++ ++ ++int efrm_nic_pre_reset(struct efhw_nic *nic) ++{ ++ struct efrm_nic *rnic = efrm_nic(nic); ++ struct efrm_client *client; ++ struct efrm_resource *rs; ++ struct list_head *client_link; ++ struct list_head *rs_link; ++ irq_flags_t lock_flags; ++ ++ spin_lock_irqsave(&efrm_nic_tablep->lock, lock_flags); ++ list_for_each(client_link, &rnic->clients) { ++ client = container_of(client_link, struct efrm_client, link); ++ EFRM_ERR("%s: client %p", __func__, client); ++ if (client->callbacks->pre_reset) ++ client->callbacks->pre_reset(client, client->user_data); ++ list_for_each(rs_link, &client->resources) { ++ rs = container_of(rs_link, struct efrm_resource, ++ rs_client_link); ++ EFRM_ERR("%s: resource %p", __func__, rs); ++ /* TODO: mark rs defunct */ ++ } ++ } ++ spin_unlock_irqrestore(&efrm_nic_tablep->lock, lock_flags); ++ ++ return 0; ++} ++ ++ ++int efrm_nic_stop(struct efhw_nic *nic) ++{ ++ /* TODO */ ++ return 0; ++} ++ ++ ++int efrm_nic_resume(struct efhw_nic *nic) ++{ ++ /* TODO */ ++ return 0; ++} ++ ++ ++static void efrm_client_nullcb(struct efrm_client *client, void *user_data) ++{ ++} ++ ++static struct efrm_client_callbacks efrm_null_callbacks = { ++ efrm_client_nullcb, ++ efrm_client_nullcb, ++ efrm_client_nullcb ++}; ++ ++ ++int efrm_client_get(int ifindex, struct efrm_client_callbacks *callbacks, ++ void *user_data, struct efrm_client **client_out) ++{ ++ struct efrm_nic *n, *rnic = NULL; ++ irq_flags_t lock_flags; ++ struct list_head *link; ++ struct efrm_client *client; ++ ++ if (callbacks == NULL) ++ callbacks = &efrm_null_callbacks; ++ ++ client = kmalloc(sizeof(*client), GFP_KERNEL); ++ if (client == NULL) ++ return -ENOMEM; ++ ++ spin_lock_irqsave(&efrm_nic_tablep->lock, lock_flags); ++ list_for_each(link, &efrm_nics) { ++ n = container_of(link, struct efrm_nic, link); ++ if (n->efhw_nic.ifindex == ifindex || ifindex < 0) { ++ rnic = n; ++ break; ++ } ++ } ++ if (rnic) { ++ client->user_data = user_data; ++ client->callbacks = callbacks; ++ client->nic = &rnic->efhw_nic; ++ client->ref_count = 1; ++ INIT_LIST_HEAD(&client->resources); ++ list_add(&client->link, &rnic->clients); ++ } ++ spin_unlock_irqrestore(&efrm_nic_tablep->lock, lock_flags); ++ ++ if (rnic == NULL) ++ return -ENODEV; ++ ++ *client_out = client; ++ return 0; ++} ++EXPORT_SYMBOL(efrm_client_get); ++ ++ ++void efrm_client_put(struct efrm_client *client) ++{ ++ irq_flags_t lock_flags; ++ ++ EFRM_ASSERT(client->ref_count > 0); ++ ++ spin_lock_irqsave(&efrm_nic_tablep->lock, lock_flags); ++ if (--client->ref_count > 0) ++ client = NULL; ++ else ++ list_del(&client->link); ++ spin_unlock_irqrestore(&efrm_nic_tablep->lock, lock_flags); ++ kfree(client); ++} ++EXPORT_SYMBOL(efrm_client_put); ++ ++ ++struct efhw_nic *efrm_client_get_nic(struct efrm_client *client) ++{ ++ return client->nic; ++} ++EXPORT_SYMBOL(efrm_client_get_nic); +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/driverlink_new.c 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,260 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file contains driverlink code which interacts with the sfc network ++ * driver. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#include "linux_resource_internal.h" ++#include "driverlink_api.h" ++#include "kernel_compat.h" ++#include ++ ++#include ++#include ++#include ++ ++/* The DL driver and associated calls */ ++static int efrm_dl_probe(struct efx_dl_device *efrm_dev, ++ const struct net_device *net_dev, ++ const struct efx_dl_device_info *dev_info, ++ const char *silicon_rev); ++ ++static void efrm_dl_remove(struct efx_dl_device *efrm_dev); ++ ++static void efrm_dl_reset_suspend(struct efx_dl_device *efrm_dev); ++ ++static void efrm_dl_reset_resume(struct efx_dl_device *efrm_dev, int ok); ++ ++static void efrm_dl_mtu_changed(struct efx_dl_device *, int); ++static void efrm_dl_event_falcon(struct efx_dl_device *efx_dev, void *p_event); ++ ++static struct efx_dl_driver efrm_dl_driver = { ++ .name = "resource", ++ .probe = efrm_dl_probe, ++ .remove = efrm_dl_remove, ++ .reset_suspend = efrm_dl_reset_suspend, ++ .reset_resume = efrm_dl_reset_resume ++}; ++ ++static void ++init_vi_resource_dimensions(struct vi_resource_dimensions *rd, ++ const struct efx_dl_falcon_resources *res) ++{ ++ rd->evq_timer_min = res->evq_timer_min; ++ rd->evq_timer_lim = res->evq_timer_lim; ++ rd->evq_int_min = res->evq_int_min; ++ rd->evq_int_lim = res->evq_int_lim; ++ rd->rxq_min = res->rxq_min; ++ rd->rxq_lim = res->rxq_lim; ++ rd->txq_min = res->txq_min; ++ rd->txq_lim = res->txq_lim; ++ EFRM_TRACE ++ ("Using evq_int(%d-%d) evq_timer(%d-%d) RXQ(%d-%d) TXQ(%d-%d)", ++ res->evq_int_min, res->evq_int_lim, res->evq_timer_min, ++ res->evq_timer_lim, res->rxq_min, res->rxq_lim, res->txq_min, ++ res->txq_lim); ++} ++ ++static int ++efrm_dl_probe(struct efx_dl_device *efrm_dev, ++ const struct net_device *net_dev, ++ const struct efx_dl_device_info *dev_info, ++ const char *silicon_rev) ++{ ++ struct vi_resource_dimensions res_dim; ++ struct efx_dl_falcon_resources *res; ++ struct linux_efhw_nic *lnic; ++ struct pci_dev *dev; ++ struct efhw_nic *nic; ++ unsigned probe_flags = 0; ++ int non_irq_evq; ++ int rc; ++ ++ efrm_dev->priv = NULL; ++ ++ efx_dl_search_device_info(dev_info, EFX_DL_FALCON_RESOURCES, ++ struct efx_dl_falcon_resources, ++ hdr, res); ++ ++ if (res == NULL) { ++ EFRM_ERR("%s: Unable to find falcon driverlink resources", ++ __func__); ++ return -EINVAL; ++ } ++ ++ if (res->flags & EFX_DL_FALCON_USE_MSI) ++ probe_flags |= NIC_FLAG_TRY_MSI; ++ ++ dev = efrm_dev->pci_dev; ++ if (res->flags & EFX_DL_FALCON_DUAL_FUNC) { ++ unsigned vendor = dev->vendor; ++ EFRM_ASSERT(dev->bus != NULL); ++ dev = NULL; ++ ++ while ((dev = pci_get_device(vendor, FALCON_S_DEVID, dev)) ++ != NULL) { ++ EFRM_ASSERT(dev->bus != NULL); ++ /* With PCIe (since it's point to point) ++ * the slot ID is usually 0 and ++ * the bus ID changes NIC to NIC, so we really ++ * need to check both. */ ++ if (PCI_SLOT(dev->devfn) == ++ PCI_SLOT(efrm_dev->pci_dev->devfn) ++ && dev->bus->number == ++ efrm_dev->pci_dev->bus->number) ++ break; ++ } ++ if (dev == NULL) { ++ EFRM_ERR("%s: Unable to find falcon secondary " ++ "PCI device.", __func__); ++ return -ENODEV; ++ } ++ pci_dev_put(dev); ++ } ++ ++ init_vi_resource_dimensions(&res_dim, res); ++ ++ EFRM_ASSERT(res_dim.evq_timer_lim > res_dim.evq_timer_min); ++ res_dim.evq_timer_lim--; ++ non_irq_evq = res_dim.evq_timer_lim; ++ ++ rc = efrm_nic_add(dev, probe_flags, net_dev->dev_addr, &lnic, ++ res->biu_lock, ++ res->buffer_table_min, res->buffer_table_lim, ++ non_irq_evq, &res_dim); ++ if (rc != 0) ++ return rc; ++ ++ nic = &lnic->efrm_nic.efhw_nic; ++ nic->mtu = net_dev->mtu + ETH_HLEN; ++ nic->net_driver_dev = efrm_dev; ++ nic->ifindex = net_dev->ifindex; ++#ifdef CONFIG_NET_NS ++ nic->nd_net = net_dev->nd_net; ++#endif ++ efrm_dev->priv = nic; ++ ++ /* Register a callback so we're told when MTU changes. ++ * We dynamically allocate efx_dl_callbacks, because ++ * the callbacks that we want depends on the NIC type. ++ */ ++ lnic->dl_callbacks = ++ kmalloc(sizeof(struct efx_dl_callbacks), GFP_KERNEL); ++ if (!lnic->dl_callbacks) { ++ EFRM_ERR("Out of memory (%s)", __func__); ++ efrm_nic_del(lnic); ++ return -ENOMEM; ++ } ++ memset(lnic->dl_callbacks, 0, sizeof(*lnic->dl_callbacks)); ++ lnic->dl_callbacks->mtu_changed = efrm_dl_mtu_changed; ++ ++ if ((res->flags & EFX_DL_FALCON_DUAL_FUNC) == 0) { ++ /* Net driver receives all management events. ++ * Register a callback to receive the ones ++ * we're interested in. */ ++ lnic->dl_callbacks->event = efrm_dl_event_falcon; ++ } ++ ++ rc = efx_dl_register_callbacks(efrm_dev, lnic->dl_callbacks); ++ if (rc < 0) { ++ EFRM_ERR("%s: efx_dl_register_callbacks failed (%d)", ++ __func__, rc); ++ kfree(lnic->dl_callbacks); ++ efrm_nic_del(lnic); ++ return rc; ++ } ++ ++ return 0; ++} ++ ++/* When we unregister ourselves on module removal, this function will be ++ * called for all the devices we claimed */ ++static void efrm_dl_remove(struct efx_dl_device *efrm_dev) ++{ ++ struct efhw_nic *nic = efrm_dev->priv; ++ struct linux_efhw_nic *lnic = linux_efhw_nic(nic); ++ EFRM_TRACE("%s called", __func__); ++ if (lnic->dl_callbacks) { ++ efx_dl_unregister_callbacks(efrm_dev, lnic->dl_callbacks); ++ kfree(lnic->dl_callbacks); ++ } ++ if (efrm_dev->priv) ++ efrm_nic_del(lnic); ++ EFRM_TRACE("%s OK", __func__); ++} ++ ++static void efrm_dl_reset_suspend(struct efx_dl_device *efrm_dev) ++{ ++ EFRM_NOTICE("%s:", __func__); ++} ++ ++static void efrm_dl_reset_resume(struct efx_dl_device *efrm_dev, int ok) ++{ ++ EFRM_NOTICE("%s: ok=%d", __func__, ok); ++} ++ ++int efrm_driverlink_register(void) ++{ ++ EFRM_TRACE("%s:", __func__); ++ return efx_dl_register_driver(&efrm_dl_driver); ++} ++ ++void efrm_driverlink_unregister(void) ++{ ++ EFRM_TRACE("%s:", __func__); ++ efx_dl_unregister_driver(&efrm_dl_driver); ++} ++ ++static void efrm_dl_mtu_changed(struct efx_dl_device *efx_dev, int mtu) ++{ ++ struct efhw_nic *nic = efx_dev->priv; ++ ++ ASSERT_RTNL(); /* Since we're looking at efx_dl_device::port_net_dev */ ++ ++ EFRM_TRACE("%s: old=%d new=%d", __func__, nic->mtu, mtu + ETH_HLEN); ++ /* If this happened we must have agreed to it above */ ++ nic->mtu = mtu + ETH_HLEN; ++} ++ ++static void efrm_dl_event_falcon(struct efx_dl_device *efx_dev, void *p_event) ++{ ++ struct efhw_nic *nic = efx_dev->priv; ++ struct linux_efhw_nic *lnic = linux_efhw_nic(nic); ++ efhw_event_t *ev = p_event; ++ ++ switch (FALCON_EVENT_CODE(ev)) { ++ case FALCON_EVENT_CODE_CHAR: ++ falcon_handle_char_event(nic, lnic->ev_handlers, ev); ++ break; ++ default: ++ EFRM_WARN("%s: unknown event type=%x", __func__, ++ (unsigned)FALCON_EVENT_CODE(ev)); ++ break; ++ } ++} +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/efrm_internal.h 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,41 @@ ++#ifndef __EFRM_INTERNAL_H__ ++#define __EFRM_INTERNAL_H__ ++ ++ ++struct filter_resource { ++ struct efrm_resource rs; ++ struct vi_resource *pt; ++ int filter_idx; ++}; ++ ++#define filter_resource(rs1) container_of((rs1), struct filter_resource, rs) ++ ++ ++struct efrm_client { ++ void *user_data; ++ struct list_head link; ++ struct efrm_client_callbacks *callbacks; ++ struct efhw_nic *nic; ++ int ref_count; ++ struct list_head resources; ++}; ++ ++ ++extern void efrm_client_add_resource(struct efrm_client *, ++ struct efrm_resource *); ++ ++extern int efrm_buffer_table_size(void); ++ ++ ++static inline void efrm_resource_init(struct efrm_resource *rs, ++ int type, int instance) ++{ ++ EFRM_ASSERT(instance >= 0); ++ EFRM_ASSERT(type >= 0 && type < EFRM_RESOURCE_NUM); ++ rs->rs_ref_count = 1; ++ rs->rs_handle.handle = (type << 28u) | ++ (((unsigned)jiffies & 0xfff) << 16) | instance; ++} ++ ++ ++#endif /* __EFRM_INTERNAL_H__ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/efx_vi_shm.c 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,707 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file provides implementation of EFX VI API, used from Xen ++ * acceleration driver. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#include "linux_resource_internal.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include "kernel_compat.h" ++ ++#if EFX_VI_STATIC_FILTERS ++struct filter_list_t { ++ struct filter_list_t *next; ++ struct filter_resource *fres; ++}; ++#endif ++ ++struct efx_vi_state { ++ struct vi_resource *vi_res; ++ ++ int ifindex; ++ struct efrm_client *efrm_client; ++ struct efhw_nic *nic; ++ ++ void (*callback_fn)(void *arg, int is_timeout); ++ void *callback_arg; ++ ++ struct completion flush_completion; ++ ++#if EFX_VI_STATIC_FILTERS ++ struct filter_list_t fres[EFX_VI_STATIC_FILTERS]; ++ struct filter_list_t *free_fres; ++ struct filter_list_t *used_fres; ++#endif ++}; ++ ++static void efx_vi_flush_complete(void *state_void) ++{ ++ struct efx_vi_state *state = (struct efx_vi_state *)state_void; ++ ++ complete(&state->flush_completion); ++} ++ ++static inline int alloc_ep(struct efx_vi_state *state) ++{ ++ int rc; ++ ++ rc = efrm_vi_resource_alloc(state->efrm_client, NULL, EFHW_VI_JUMBO_EN, ++ efx_vi_eventq_size, ++ FALCON_DMA_Q_DEFAULT_TX_SIZE, ++ FALCON_DMA_Q_DEFAULT_RX_SIZE, ++ 0, 0, &state->vi_res, NULL, NULL, NULL, ++ NULL); ++ if (rc < 0) { ++ EFRM_ERR("%s: ERROR efrm_vi_resource_alloc error %d", ++ __func__, rc); ++ return rc; ++ } ++ ++ efrm_vi_register_flush_callback(state->vi_res, &efx_vi_flush_complete, ++ (void *)state); ++ ++ return 0; ++} ++ ++static int free_ep(struct efx_vi_state *efx_state) ++{ ++ efrm_vi_resource_release(efx_state->vi_res); ++ ++ return 0; ++} ++ ++#if EFX_VI_STATIC_FILTERS ++static int efx_vi_alloc_static_filters(struct efx_vi_state *efx_state) ++{ ++ int i; ++ int rc; ++ ++ efx_state->free_fres = efx_state->used_fres = NULL; ++ ++ for (i = 0; i < EFX_VI_STATIC_FILTERS; i++) { ++ rc = efrm_filter_resource_alloc(efx_state->vi_res, ++ &efx_state->fres[i].fres); ++ if (rc < 0) { ++ EFRM_ERR("%s: efrm_filter_resource_alloc failed: %d", ++ __func__, rc); ++ while (i > 0) { ++ i--; ++ efrm_filter_resource_release(efx_state-> ++ fres[i].fres); ++ } ++ efx_state->free_fres = NULL; ++ return rc; ++ } ++ efx_state->fres[i].next = efx_state->free_fres; ++ efx_state->free_fres = &efx_state->fres[i]; ++ } ++ ++ return 0; ++} ++#endif ++ ++int efx_vi_alloc(struct efx_vi_state **vih_out, int ifindex) ++{ ++ struct efx_vi_state *efx_state; ++ int rc; ++ ++ efx_state = kmalloc(sizeof(struct efx_vi_state), GFP_KERNEL); ++ ++ if (!efx_state) { ++ EFRM_ERR("%s: failed to allocate memory for efx_vi_state", ++ __func__); ++ rc = -ENOMEM; ++ goto fail; ++ } ++ ++ efx_state->ifindex = ifindex; ++ rc = efrm_client_get(ifindex, NULL, NULL, &efx_state->efrm_client); ++ if (rc < 0) { ++ EFRM_ERR("%s: efrm_client_get(%d) failed: %d", __func__, ++ ifindex, rc); ++ rc = -ENODEV; ++ goto fail_no_ifindex; ++ } ++ efx_state->nic = efrm_client_get_nic(efx_state->efrm_client); ++ ++ init_completion(&efx_state->flush_completion); ++ ++ /* basically allocate_pt_endpoint() */ ++ rc = alloc_ep(efx_state); ++ if (rc) { ++ EFRM_ERR("%s: alloc_ep failed: %d", __func__, rc); ++ goto fail_no_pt; ++ } ++#if EFX_VI_STATIC_FILTERS ++ /* Statically allocate a set of filter resources - removes the ++ restriction on not being able to use efx_vi_filter() from ++ in_atomic() */ ++ rc = efx_vi_alloc_static_filters(efx_state); ++ if (rc) ++ goto fail_no_filters; ++#endif ++ ++ *vih_out = efx_state; ++ ++ return 0; ++#if EFX_VI_STATIC_FILTERS ++fail_no_filters: ++ free_ep(efx_state); ++#endif ++fail_no_pt: ++ efrm_client_put(efx_state->efrm_client); ++fail_no_ifindex: ++ kfree(efx_state); ++fail: ++ return rc; ++} ++EXPORT_SYMBOL(efx_vi_alloc); ++ ++void efx_vi_free(struct efx_vi_state *vih) ++{ ++ struct efx_vi_state *efx_state = vih; ++ ++ /* TODO flush dma channels, init dma queues?. See ef_free_vnic() */ ++#if EFX_VI_STATIC_FILTERS ++ int i; ++ ++ for (i = 0; i < EFX_VI_STATIC_FILTERS; i++) ++ efrm_filter_resource_release(efx_state->fres[i].fres); ++#endif ++ ++ if (efx_state->vi_res) ++ free_ep(efx_state); ++ ++ efrm_client_put(efx_state->efrm_client); ++ ++ kfree(efx_state); ++} ++EXPORT_SYMBOL(efx_vi_free); ++ ++void efx_vi_reset(struct efx_vi_state *vih) ++{ ++ struct efx_vi_state *efx_state = vih; ++ ++ efrm_pt_flush(efx_state->vi_res); ++ ++ while (wait_for_completion_timeout(&efx_state->flush_completion, HZ) ++ == 0) ++ efrm_vi_resource_flush_retry(efx_state->vi_res); ++ ++ /* Bosch the eventq */ ++ efrm_eventq_reset(efx_state->vi_res); ++ return; ++} ++EXPORT_SYMBOL(efx_vi_reset); ++ ++static void ++efx_vi_eventq_callback(void *context, int is_timeout, struct efhw_nic *nic) ++{ ++ struct efx_vi_state *efx_state = (struct efx_vi_state *)context; ++ ++ EFRM_ASSERT(efx_state->callback_fn); ++ ++ return efx_state->callback_fn(efx_state->callback_arg, is_timeout); ++} ++ ++int ++efx_vi_eventq_register_callback(struct efx_vi_state *vih, ++ void (*callback)(void *context, int is_timeout), ++ void *context) ++{ ++ struct efx_vi_state *efx_state = vih; ++ ++ efx_state->callback_fn = callback; ++ efx_state->callback_arg = context; ++ ++ /* Register the eventq timeout event callback */ ++ efrm_eventq_register_callback(efx_state->vi_res, ++ efx_vi_eventq_callback, efx_state); ++ ++ return 0; ++} ++EXPORT_SYMBOL(efx_vi_eventq_register_callback); ++ ++int efx_vi_eventq_kill_callback(struct efx_vi_state *vih) ++{ ++ struct efx_vi_state *efx_state = vih; ++ ++ if (efx_state->vi_res->evq_callback_fn) ++ efrm_eventq_kill_callback(efx_state->vi_res); ++ ++ efx_state->callback_fn = NULL; ++ efx_state->callback_arg = NULL; ++ ++ return 0; ++} ++EXPORT_SYMBOL(efx_vi_eventq_kill_callback); ++ ++struct efx_vi_dma_map_state { ++ struct efhw_buffer_table_allocation bt_handle; ++ int n_pages; ++ dma_addr_t *dma_addrs; ++}; ++ ++int ++efx_vi_dma_map_pages(struct efx_vi_state *vih, struct page **pages, ++ int n_pages, struct efx_vi_dma_map_state **dmh_out) ++{ ++ struct efx_vi_state *efx_state = vih; ++ int order = fls(n_pages - 1), rc, i, evq_id; ++ dma_addr_t dma_addr; ++ struct efx_vi_dma_map_state *dm_state; ++ ++ if (n_pages != (1 << order)) { ++ EFRM_WARN("%s: Can only allocate buffers in power of 2 " ++ "sizes (not %d)", __func__, n_pages); ++ return -EINVAL; ++ } ++ ++ dm_state = kmalloc(sizeof(struct efx_vi_dma_map_state), GFP_KERNEL); ++ if (!dm_state) ++ return -ENOMEM; ++ ++ dm_state->dma_addrs = kmalloc(sizeof(dma_addr_t) * n_pages, ++ GFP_KERNEL); ++ if (!dm_state->dma_addrs) { ++ kfree(dm_state); ++ return -ENOMEM; ++ } ++ ++ rc = efrm_buffer_table_alloc(order, &dm_state->bt_handle); ++ if (rc < 0) { ++ kfree(dm_state->dma_addrs); ++ kfree(dm_state); ++ return rc; ++ } ++ ++ evq_id = EFRM_RESOURCE_INSTANCE(efx_state->vi_res->rs.rs_handle); ++ for (i = 0; i < n_pages; i++) { ++ /* TODO do we need to get_page() here ? */ ++ ++ dma_addr = pci_map_page(linux_efhw_nic(efx_state->nic)-> ++ pci_dev, pages[i], 0, PAGE_SIZE, ++ PCI_DMA_TODEVICE); ++ ++ efrm_buffer_table_set(&dm_state->bt_handle, efx_state->nic, ++ i, dma_addr, evq_id); ++ ++ dm_state->dma_addrs[i] = dma_addr; ++ ++ /* Would be nice to not have to call commit each time, but ++ * comment says there are hardware restrictions on how often ++ * you can go without it, so do this to be safe */ ++ efrm_buffer_table_commit(); ++ } ++ ++ dm_state->n_pages = n_pages; ++ ++ *dmh_out = dm_state; ++ ++ return 0; ++} ++EXPORT_SYMBOL(efx_vi_dma_map_pages); ++ ++/* Function needed as Xen can't get pages for grants in dom0, but can ++ get dma address */ ++int ++efx_vi_dma_map_addrs(struct efx_vi_state *vih, ++ unsigned long long *bus_dev_addrs, ++ int n_pages, struct efx_vi_dma_map_state **dmh_out) ++{ ++ struct efx_vi_state *efx_state = vih; ++ int order = fls(n_pages - 1), rc, i, evq_id; ++ dma_addr_t dma_addr; ++ struct efx_vi_dma_map_state *dm_state; ++ ++ if (n_pages != (1 << order)) { ++ EFRM_WARN("%s: Can only allocate buffers in power of 2 " ++ "sizes (not %d)", __func__, n_pages); ++ return -EINVAL; ++ } ++ ++ dm_state = kmalloc(sizeof(struct efx_vi_dma_map_state), GFP_KERNEL); ++ if (!dm_state) ++ return -ENOMEM; ++ ++ dm_state->dma_addrs = kmalloc(sizeof(dma_addr_t) * n_pages, ++ GFP_KERNEL); ++ if (!dm_state->dma_addrs) { ++ kfree(dm_state); ++ return -ENOMEM; ++ } ++ ++ rc = efrm_buffer_table_alloc(order, &dm_state->bt_handle); ++ if (rc < 0) { ++ kfree(dm_state->dma_addrs); ++ kfree(dm_state); ++ return rc; ++ } ++ ++ evq_id = EFRM_RESOURCE_INSTANCE(efx_state->vi_res->rs.rs_handle); ++#if 0 ++ EFRM_WARN("%s: mapping %d pages to evq %d, bt_ids %d-%d\n", ++ __func__, n_pages, evq_id, ++ dm_state->bt_handle.base, ++ dm_state->bt_handle.base + n_pages); ++#endif ++ for (i = 0; i < n_pages; i++) { ++ ++ dma_addr = (dma_addr_t)bus_dev_addrs[i]; ++ ++ efrm_buffer_table_set(&dm_state->bt_handle, efx_state->nic, ++ i, dma_addr, evq_id); ++ ++ dm_state->dma_addrs[i] = dma_addr; ++ ++ /* Would be nice to not have to call commit each time, but ++ * comment says there are hardware restrictions on how often ++ * you can go without it, so do this to be safe */ ++ efrm_buffer_table_commit(); ++ } ++ ++ dm_state->n_pages = n_pages; ++ ++ *dmh_out = dm_state; ++ ++ return 0; ++} ++EXPORT_SYMBOL(efx_vi_dma_map_addrs); ++ ++void ++efx_vi_dma_unmap_pages(struct efx_vi_state *vih, ++ struct efx_vi_dma_map_state *dmh) ++{ ++ struct efx_vi_state *efx_state = vih; ++ struct efx_vi_dma_map_state *dm_state = ++ (struct efx_vi_dma_map_state *)dmh; ++ int i; ++ ++ efrm_buffer_table_free(&dm_state->bt_handle); ++ ++ for (i = 0; i < dm_state->n_pages; ++i) ++ pci_unmap_page(linux_efhw_nic(efx_state->nic)->pci_dev, ++ dm_state->dma_addrs[i], PAGE_SIZE, ++ PCI_DMA_TODEVICE); ++ ++ kfree(dm_state->dma_addrs); ++ kfree(dm_state); ++ ++ return; ++} ++EXPORT_SYMBOL(efx_vi_dma_unmap_pages); ++ ++void ++efx_vi_dma_unmap_addrs(struct efx_vi_state *vih, ++ struct efx_vi_dma_map_state *dmh) ++{ ++ struct efx_vi_dma_map_state *dm_state = ++ (struct efx_vi_dma_map_state *)dmh; ++ ++ efrm_buffer_table_free(&dm_state->bt_handle); ++ ++ kfree(dm_state->dma_addrs); ++ kfree(dm_state); ++ ++ return; ++} ++EXPORT_SYMBOL(efx_vi_dma_unmap_addrs); ++ ++unsigned ++efx_vi_dma_get_map_addr(struct efx_vi_state *vih, ++ struct efx_vi_dma_map_state *dmh) ++{ ++ struct efx_vi_dma_map_state *dm_state = ++ (struct efx_vi_dma_map_state *)dmh; ++ ++ return EFHW_BUFFER_ADDR(dm_state->bt_handle.base, 0); ++} ++EXPORT_SYMBOL(efx_vi_dma_get_map_addr); ++ ++#if EFX_VI_STATIC_FILTERS ++static int ++get_filter(struct efx_vi_state *efx_state, ++ efrm_resource_handle_t pthandle, struct filter_resource **fres_out) ++{ ++ struct filter_list_t *flist; ++ if (efx_state->free_fres == NULL) ++ return -ENOMEM; ++ else { ++ flist = efx_state->free_fres; ++ efx_state->free_fres = flist->next; ++ flist->next = efx_state->used_fres; ++ efx_state->used_fres = flist; ++ *fres_out = flist->fres; ++ return 0; ++ } ++} ++#endif ++ ++static void ++release_filter(struct efx_vi_state *efx_state, struct filter_resource *fres) ++{ ++#if EFX_VI_STATIC_FILTERS ++ struct filter_list_t *flist = efx_state->used_fres, *prev = NULL; ++ while (flist) { ++ if (flist->fres == fres) { ++ if (prev) ++ prev->next = flist->next; ++ else ++ efx_state->used_fres = flist->next; ++ flist->next = efx_state->free_fres; ++ efx_state->free_fres = flist; ++ return; ++ } ++ prev = flist; ++ flist = flist->next; ++ } ++ EFRM_ERR("%s: couldn't find filter", __func__); ++#else ++ return efrm_filter_resource_release(fres); ++#endif ++} ++ ++int ++efx_vi_filter(struct efx_vi_state *vih, int protocol, ++ unsigned ip_addr_be32, int port_le16, ++ struct filter_resource_t **fh_out) ++{ ++ struct efx_vi_state *efx_state = vih; ++ struct filter_resource *uninitialized_var(frs); ++ int rc; ++ ++#if EFX_VI_STATIC_FILTERS ++ rc = get_filter(efx_state, efx_state->vi_res->rs.rs_handle, &frs); ++#else ++ rc = efrm_filter_resource_alloc(efx_state->vi_res, &frs); ++#endif ++ if (rc < 0) ++ return rc; ++ ++ /* Add the hardware filter. We pass in the source port and address ++ * as 0 (wildcard) to minimise the number of filters needed. */ ++ if (protocol == IPPROTO_TCP) { ++ rc = efrm_filter_resource_tcp_set(frs, 0, 0, ip_addr_be32, ++ port_le16); ++ } else { ++ rc = efrm_filter_resource_udp_set(frs, 0, 0, ip_addr_be32, ++ port_le16); ++ } ++ ++ *fh_out = (struct filter_resource_t *)frs; ++ ++ return rc; ++} ++EXPORT_SYMBOL(efx_vi_filter); ++ ++int ++efx_vi_filter_stop(struct efx_vi_state *vih, struct filter_resource_t *fh) ++{ ++ struct efx_vi_state *efx_state = vih; ++ struct filter_resource *frs = (struct filter_resource *)fh; ++ int rc; ++ ++ rc = efrm_filter_resource_clear(frs); ++ release_filter(efx_state, frs); ++ ++ return rc; ++} ++EXPORT_SYMBOL(efx_vi_filter_stop); ++ ++int ++efx_vi_hw_resource_get_virt(struct efx_vi_state *vih, ++ struct efx_vi_hw_resource_metadata *mdata, ++ struct efx_vi_hw_resource *hw_res_array, ++ int *length) ++{ ++ EFRM_NOTICE("%s: TODO!", __func__); ++ ++ return 0; ++} ++EXPORT_SYMBOL(efx_vi_hw_resource_get_virt); ++ ++int ++efx_vi_hw_resource_get_phys(struct efx_vi_state *vih, ++ struct efx_vi_hw_resource_metadata *mdata, ++ struct efx_vi_hw_resource *hw_res_array, ++ int *length) ++{ ++ struct efx_vi_state *efx_state = vih; ++ struct linux_efhw_nic *lnic = linux_efhw_nic(efx_state->nic); ++ unsigned long phys = lnic->ctr_ap_pci_addr; ++ struct efrm_resource *ep_res = &efx_state->vi_res->rs; ++ unsigned ep_mmap_bytes; ++ int i; ++ ++ if (*length < EFX_VI_HW_RESOURCE_MAXSIZE) ++ return -EINVAL; ++ ++ mdata->nic_arch = efx_state->nic->devtype.arch; ++ mdata->nic_variant = efx_state->nic->devtype.variant; ++ mdata->nic_revision = efx_state->nic->devtype.revision; ++ ++ mdata->evq_order = ++ efx_state->vi_res->nic_info.evq_pages.iobuff.order; ++ mdata->evq_offs = efx_state->vi_res->nic_info.evq_pages.iobuff_off; ++ mdata->evq_capacity = efx_vi_eventq_size; ++ mdata->instance = EFRM_RESOURCE_INSTANCE(ep_res->rs_handle); ++ mdata->rx_capacity = FALCON_DMA_Q_DEFAULT_RX_SIZE; ++ mdata->tx_capacity = FALCON_DMA_Q_DEFAULT_TX_SIZE; ++ ++ ep_mmap_bytes = FALCON_DMA_Q_DEFAULT_MMAP; ++ EFRM_ASSERT(ep_mmap_bytes == PAGE_SIZE * 2); ++ ++#ifndef NDEBUG ++ { ++ /* Sanity about doorbells */ ++ unsigned long tx_dma_page_addr, rx_dma_page_addr; ++ ++ /* get rx doorbell address */ ++ rx_dma_page_addr = ++ phys + falcon_rx_dma_page_addr(mdata->instance); ++ /* get tx doorbell address */ ++ tx_dma_page_addr = ++ phys + falcon_tx_dma_page_addr(mdata->instance); ++ ++ /* Check the lower bits of the TX doorbell will be ++ * consistent. */ ++ EFRM_ASSERT((TX_DESC_UPD_REG_PAGE4_OFST & ++ FALCON_DMA_PAGE_MASK) == ++ (TX_DESC_UPD_REG_PAGE123K_OFST & ++ FALCON_DMA_PAGE_MASK)); ++ ++ /* Check the lower bits of the RX doorbell will be ++ * consistent. */ ++ EFRM_ASSERT((RX_DESC_UPD_REG_PAGE4_OFST & ++ FALCON_DMA_PAGE_MASK) == ++ (RX_DESC_UPD_REG_PAGE123K_OFST & ++ FALCON_DMA_PAGE_MASK)); ++ ++ /* Check that the doorbells will be in the same page. */ ++ EFRM_ASSERT((TX_DESC_UPD_REG_PAGE4_OFST & PAGE_MASK) == ++ (RX_DESC_UPD_REG_PAGE4_OFST & PAGE_MASK)); ++ ++ /* Check that the doorbells are in the same page. */ ++ EFRM_ASSERT((tx_dma_page_addr & PAGE_MASK) == ++ (rx_dma_page_addr & PAGE_MASK)); ++ ++ /* Check that the TX doorbell offset is correct. */ ++ EFRM_ASSERT((TX_DESC_UPD_REG_PAGE4_OFST & ~PAGE_MASK) == ++ (tx_dma_page_addr & ~PAGE_MASK)); ++ ++ /* Check that the RX doorbell offset is correct. */ ++ EFRM_ASSERT((RX_DESC_UPD_REG_PAGE4_OFST & ~PAGE_MASK) == ++ (rx_dma_page_addr & ~PAGE_MASK)); ++ } ++#endif ++ ++ i = 0; ++ hw_res_array[i].type = EFX_VI_HW_RESOURCE_TXDMAQ; ++ hw_res_array[i].mem_type = EFX_VI_HW_RESOURCE_PERIPHERAL; ++ hw_res_array[i].more_to_follow = 0; ++ hw_res_array[i].length = PAGE_SIZE; ++ hw_res_array[i].address = ++ (unsigned long)efx_state->vi_res->nic_info. ++ dmaq_pages[EFRM_VI_RM_DMA_QUEUE_TX].kva; ++ ++ i++; ++ hw_res_array[i].type = EFX_VI_HW_RESOURCE_RXDMAQ; ++ hw_res_array[i].mem_type = EFX_VI_HW_RESOURCE_PERIPHERAL; ++ hw_res_array[i].more_to_follow = 0; ++ hw_res_array[i].length = PAGE_SIZE; ++ hw_res_array[i].address = ++ (unsigned long)efx_state->vi_res->nic_info. ++ dmaq_pages[EFRM_VI_RM_DMA_QUEUE_RX].kva; ++ ++ i++; ++ hw_res_array[i].type = EFX_VI_HW_RESOURCE_EVQTIMER; ++ hw_res_array[i].mem_type = EFX_VI_HW_RESOURCE_PERIPHERAL; ++ hw_res_array[i].more_to_follow = 0; ++ hw_res_array[i].length = PAGE_SIZE; ++ hw_res_array[i].address = ++ (unsigned long)phys + falcon_timer_page_addr(mdata->instance); ++ ++ /* NB EFX_VI_HW_RESOURCE_EVQPTR not used on Falcon */ ++ ++ i++; ++ switch (efx_state->nic->devtype.variant) { ++ case 'A': ++ hw_res_array[i].type = EFX_VI_HW_RESOURCE_EVQRPTR; ++ hw_res_array[i].mem_type = EFX_VI_HW_RESOURCE_PERIPHERAL; ++ hw_res_array[i].more_to_follow = 0; ++ hw_res_array[i].length = PAGE_SIZE; ++ hw_res_array[i].address = (unsigned long)phys + ++ EVQ_RPTR_REG_OFST + ++ (FALCON_REGISTER128 * mdata->instance); ++ break; ++ case 'B': ++ hw_res_array[i].type = EFX_VI_HW_RESOURCE_EVQRPTR_OFFSET; ++ hw_res_array[i].mem_type = EFX_VI_HW_RESOURCE_PERIPHERAL; ++ hw_res_array[i].more_to_follow = 0; ++ hw_res_array[i].length = PAGE_SIZE; ++ hw_res_array[i].address = ++ (unsigned long)FALCON_EVQ_RPTR_REG_P0; ++ break; ++ default: ++ EFRM_ASSERT(0); ++ break; ++ } ++ ++ i++; ++ hw_res_array[i].type = EFX_VI_HW_RESOURCE_EVQMEMKVA; ++ hw_res_array[i].mem_type = EFX_VI_HW_RESOURCE_IOBUFFER; ++ hw_res_array[i].more_to_follow = 0; ++ hw_res_array[i].length = PAGE_SIZE; ++ hw_res_array[i].address = (unsigned long)efx_state->vi_res-> ++ nic_info.evq_pages.iobuff.kva; ++ ++ i++; ++ hw_res_array[i].type = EFX_VI_HW_RESOURCE_BELLPAGE; ++ hw_res_array[i].mem_type = EFX_VI_HW_RESOURCE_PERIPHERAL; ++ hw_res_array[i].more_to_follow = 0; ++ hw_res_array[i].length = PAGE_SIZE; ++ hw_res_array[i].address = ++ (unsigned long)(phys + ++ falcon_tx_dma_page_addr(mdata->instance)) ++ >> PAGE_SHIFT; ++ ++ i++; ++ ++ EFRM_ASSERT(i <= *length); ++ ++ *length = i; ++ ++ return 0; ++} ++EXPORT_SYMBOL(efx_vi_hw_resource_get_phys); +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/eventq.c 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,321 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file contains event queue support. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define KEVENTQ_MAGIC 0x07111974 ++ ++/*! Helper function to allocate the iobuffer needed by an eventq ++ * - it ensures the eventq has the correct alignment for the NIC ++ * ++ * \param rm Event-queue resource manager ++ * \param instance Event-queue instance (index) ++ * \param buf_bytes Requested size of eventq ++ * \return < 0 if iobuffer allocation fails ++ */ ++int ++efhw_nic_event_queue_alloc_iobuffer(struct efhw_nic *nic, ++ struct eventq_resource_hardware *h, ++ int evq_instance, unsigned buf_bytes) ++{ ++ unsigned int page_order; ++ int rc; ++ ++ /* Allocate an iobuffer. */ ++ page_order = get_order(buf_bytes); ++ ++ h->iobuff_off = 0; ++ ++ EFHW_TRACE("allocating eventq size %x", ++ 1u << (page_order + PAGE_SHIFT)); ++ rc = efhw_iopages_alloc(nic, &h->iobuff, page_order); ++ if (rc < 0) { ++ EFHW_WARN("%s: failed to allocate %u pages", ++ __func__, 1u << page_order); ++ return rc; ++ } ++ ++ /* Set the eventq pages to match EFHW_CLEAR_EVENT() */ ++ if (EFHW_CLEAR_EVENT_VALUE) ++ memset(efhw_iopages_ptr(&h->iobuff) + h->iobuff_off, ++ EFHW_CLEAR_EVENT_VALUE, (1u << page_order) * PAGE_SIZE); ++ ++ EFHW_TRACE("%s: allocated %u pages", __func__, 1u << (page_order)); ++ ++ /* For Falcon the NIC is programmed with the base buffer address of a ++ * contiguous region of buffer space. This means that larger than a ++ * PAGE event queues can be expected to allocate even when the host's ++ * physical memory is fragmented */ ++ EFHW_ASSERT(efhw_nic_have_hw(nic)); ++ EFHW_ASSERT(page_order <= h->buf_tbl_alloc.order); ++ ++ /* Initialise the buffer table entries. */ ++ falcon_nic_buffer_table_set_n(nic, h->buf_tbl_alloc.base, ++ efhw_iopages_dma_addr(&h->iobuff) + ++ h->iobuff_off, EFHW_NIC_PAGE_SIZE, 0, ++ 1 << page_order, 0); ++ ++ if (evq_instance >= FALCON_EVQ_TBL_RESERVED) ++ falcon_nic_buffer_table_confirm(nic); ++ return 0; ++} ++ ++/********************************************************************** ++ * Kernel event queue management. ++ */ ++ ++/* Values for [struct efhw_keventq::lock] field. */ ++#define KEVQ_UNLOCKED 0 ++#define KEVQ_LOCKED 1 ++#define KEVQ_RECHECK 2 ++ ++int ++efhw_keventq_ctor(struct efhw_nic *nic, int instance, ++ struct efhw_keventq *evq, ++ struct efhw_ev_handler *ev_handlers) ++{ ++ int rc; ++ unsigned buf_bytes = evq->hw.capacity * sizeof(efhw_event_t); ++ ++ evq->instance = instance; ++ evq->ev_handlers = ev_handlers; ++ ++ /* allocate an IObuffer for the eventq */ ++ rc = efhw_nic_event_queue_alloc_iobuffer(nic, &evq->hw, evq->instance, ++ buf_bytes); ++ if (rc < 0) ++ return rc; ++ ++ /* Zero the timer-value for this queue. ++ AND Tell the nic about the event queue. */ ++ efhw_nic_event_queue_enable(nic, evq->instance, evq->hw.capacity, ++ efhw_iopages_dma_addr(&evq->hw.iobuff) + ++ evq->hw.iobuff_off, ++ evq->hw.buf_tbl_alloc.base, ++ 1 /* interrupting */); ++ ++ evq->lock = KEVQ_UNLOCKED; ++ evq->evq_base = efhw_iopages_ptr(&evq->hw.iobuff) + evq->hw.iobuff_off; ++ evq->evq_ptr = 0; ++ evq->evq_mask = (evq->hw.capacity * sizeof(efhw_event_t)) - 1u; ++ ++ EFHW_TRACE("%s: [%d] base=%p end=%p", __func__, evq->instance, ++ evq->evq_base, evq->evq_base + buf_bytes); ++ ++ return 0; ++} ++ ++void efhw_keventq_dtor(struct efhw_nic *nic, struct efhw_keventq *evq) ++{ ++ EFHW_ASSERT(evq); ++ ++ EFHW_TRACE("%s: [%d]", __func__, evq->instance); ++ ++ /* Zero the timer-value for this queue. ++ And Tell NIC to stop using this event queue. */ ++ efhw_nic_event_queue_disable(nic, evq->instance, 0); ++ ++ /* free the pages used by the eventq itself */ ++ efhw_iopages_free(nic, &evq->hw.iobuff); ++} ++ ++void ++efhw_handle_txdmaq_flushed(struct efhw_nic *nic, struct efhw_ev_handler *h, ++ efhw_event_t *evp) ++{ ++ int instance = (int)FALCON_EVENT_TX_FLUSH_Q_ID(evp); ++ EFHW_TRACE("%s: instance=%d", __func__, instance); ++ ++ if (!h->dmaq_flushed_fn) { ++ EFHW_WARN("%s: no handler registered", __func__); ++ return; ++ } ++ ++ h->dmaq_flushed_fn(nic, instance, false); ++} ++ ++void ++efhw_handle_rxdmaq_flushed(struct efhw_nic *nic, struct efhw_ev_handler *h, ++ efhw_event_t *evp) ++{ ++ unsigned instance = (unsigned)FALCON_EVENT_RX_FLUSH_Q_ID(evp); ++ EFHW_TRACE("%s: instance=%d", __func__, instance); ++ ++ if (!h->dmaq_flushed_fn) { ++ EFHW_WARN("%s: no handler registered", __func__); ++ return; ++ } ++ ++ h->dmaq_flushed_fn(nic, instance, true); ++} ++ ++void ++efhw_handle_wakeup_event(struct efhw_nic *nic, struct efhw_ev_handler *h, ++ efhw_event_t *evp) ++{ ++ unsigned instance = (unsigned)FALCON_EVENT_WAKE_EVQ_ID(evp); ++ ++ if (!h->wakeup_fn) { ++ EFHW_WARN("%s: no handler registered", __func__); ++ return; ++ } ++ ++ h->wakeup_fn(nic, instance); ++} ++ ++void ++efhw_handle_timeout_event(struct efhw_nic *nic, struct efhw_ev_handler *h, ++ efhw_event_t *evp) ++{ ++ unsigned instance = (unsigned)FALCON_EVENT_WAKE_EVQ_ID(evp); ++ ++ if (!h->timeout_fn) { ++ EFHW_WARN("%s: no handler registered", __func__); ++ return; ++ } ++ ++ h->timeout_fn(nic, instance); ++} ++ ++/********************************************************************** ++ * Kernel event queue event handling. ++ */ ++ ++int efhw_keventq_poll(struct efhw_nic *nic, struct efhw_keventq *q) ++{ ++ efhw_event_t *ev; ++ int l, count = 0; ++ ++ EFHW_ASSERT(nic); ++ EFHW_ASSERT(q); ++ EFHW_ASSERT(q->ev_handlers); ++ ++ /* Acquire the lock, or mark the queue as needing re-checking. */ ++ for (;;) { ++ l = q->lock; ++ if (l == KEVQ_UNLOCKED) { ++ if ((int)cmpxchg(&q->lock, l, KEVQ_LOCKED) == l) ++ break; ++ } else if (l == KEVQ_LOCKED) { ++ if ((int)cmpxchg(&q->lock, l, KEVQ_RECHECK) == l) ++ return 0; ++ } else { /* already marked for re-checking */ ++ EFHW_ASSERT(l == KEVQ_RECHECK); ++ return 0; ++ } ++ } ++ ++ if (unlikely(EFHW_EVENT_OVERFLOW(q, q))) ++ goto overflow; ++ ++ ev = EFHW_EVENT_PTR(q, q, 0); ++ ++#ifndef NDEBUG ++ if (!EFHW_IS_EVENT(ev)) ++ EFHW_TRACE("%s: %d NO EVENTS!", __func__, q->instance); ++#endif ++ ++ for (;;) { ++ /* Convention for return codes for handlers is: ++ ** 0 - no error, event consumed ++ ** 1 - no error, event not consumed ++ ** -ve - error, event not consumed ++ */ ++ if (likely(EFHW_IS_EVENT(ev))) { ++ count++; ++ ++ switch (FALCON_EVENT_CODE(ev)) { ++ ++ case FALCON_EVENT_CODE_CHAR: ++ falcon_handle_char_event(nic, q->ev_handlers, ++ ev); ++ break; ++ ++ default: ++ EFHW_ERR("efhw_keventq_poll: [%d] UNEXPECTED " ++ "EVENT:"FALCON_EVENT_FMT, ++ q->instance, ++ FALCON_EVENT_PRI_ARG(*ev)); ++ } ++ ++ EFHW_CLEAR_EVENT(ev); ++ EFHW_EVENTQ_NEXT(q); ++ ++ ev = EFHW_EVENT_PTR(q, q, 0); ++ } else { ++ /* No events left. Release the lock (checking if we ++ * need to re-poll to avoid race). */ ++ l = q->lock; ++ if (l == KEVQ_LOCKED) { ++ if ((int)cmpxchg(&q->lock, l, KEVQ_UNLOCKED) ++ == l) { ++ EFHW_TRACE ++ ("efhw_keventq_poll: %d clean exit", ++ q->instance); ++ goto clean_exit; ++ } ++ } ++ ++ /* Potentially more work to do. */ ++ l = q->lock; ++ EFHW_ASSERT(l == KEVQ_RECHECK); ++ EFHW_TEST((int)cmpxchg(&q->lock, l, KEVQ_LOCKED) == l); ++ EFHW_TRACE("efhw_keventq_poll: %d re-poll required", ++ q->instance); ++ } ++ } ++ ++ /* shouldn't get here */ ++ EFHW_ASSERT(0); ++ ++overflow: ++ /* ?? Oh dear. Should we poll everything that could have possibly ++ ** happened? Or merely cry out in anguish... ++ */ ++ EFHW_WARN("efhw_keventq_poll: %d ***** OVERFLOW nic %d *****", ++ q->instance, nic->index); ++ ++ q->lock = KEVQ_UNLOCKED; ++ return count; ++ ++clean_exit: ++ /* Ack the processed events so that this event queue can potentially ++ raise interrupts again */ ++ falcon_nic_evq_ack(nic, q->instance, ++ (EFHW_EVENT_OFFSET(q, q, 0) / sizeof(efhw_event_t)), ++ false); ++ return count; ++} +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/falcon.c 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,2525 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file contains Falcon hardware support. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++/*---------------------------------------------------------------------------- ++ * ++ * Workarounds and options ++ * ++ *---------------------------------------------------------------------------*/ ++ ++/* Keep a software copy of the filter table and check for duplicates. */ ++#define FALCON_FULL_FILTER_CACHE 1 ++ ++/* Read filters back from the hardware to detect corruption. */ ++#define FALCON_VERIFY_FILTERS 0 ++ ++/* Options */ ++#define RX_FILTER_CTL_SRCH_LIMIT_TCP_FULL 8 /* default search limit */ ++#define RX_FILTER_CTL_SRCH_LIMIT_TCP_WILD 8 /* default search limit */ ++#define RX_FILTER_CTL_SRCH_LIMIT_UDP_FULL 8 /* default search limit */ ++#define RX_FILTER_CTL_SRCH_LIMIT_UDP_WILD 8 /* default search limit */ ++ ++#define FALCON_MAC_SET_TYPE_BY_SPEED 0 ++ ++/* FIXME: We should detect mode at runtime. */ ++#define FALCON_BUFFER_TABLE_FULL_MODE 1 ++ ++/* "Fudge factors" - difference between programmed value and actual depth */ ++#define RX_FILTER_CTL_SRCH_FUDGE_WILD 3 /* increase the search limit */ ++#define RX_FILTER_CTL_SRCH_FUDGE_FULL 1 /* increase the search limit */ ++#define TX_FILTER_CTL_SRCH_FUDGE_WILD 3 /* increase the search limit */ ++#define TX_FILTER_CTL_SRCH_FUDGE_FULL 1 /* increase the search limit */ ++ ++/*---------------------------------------------------------------------------- ++ * ++ * Debug Macros ++ * ++ *---------------------------------------------------------------------------*/ ++ ++#define _DEBUG_SYM_ static ++ ++ /*---------------------------------------------------------------------------- ++ * ++ * Macros and forward declarations ++ * ++ *--------------------------------------------------------------------------*/ ++ ++#define FALCON_REGION_NUM 4 /* number of supported memory regions */ ++ ++#define FALCON_BUFFER_TBL_HALF_BYTES 4 ++#define FALCON_BUFFER_TBL_FULL_BYTES 8 ++ ++/* Shadow buffer table - hack for testing only */ ++#if FALCON_BUFFER_TABLE_FULL_MODE == 0 ++# define FALCON_USE_SHADOW_BUFFER_TABLE 1 ++#else ++# define FALCON_USE_SHADOW_BUFFER_TABLE 0 ++#endif ++ ++ ++/*---------------------------------------------------------------------------- ++ * ++ * Header assertion checks ++ * ++ *---------------------------------------------------------------------------*/ ++ ++#define FALCON_ASSERT_VALID() /* nothing yet */ ++ ++/* Falcon has a 128bit register model but most registers have useful ++ defaults or only implement a small number of bits. Some registers ++ can be programmed 32bits UNLOCKED all others should be interlocked ++ against other threads within the same protection domain. ++ ++ Aim is for software to perform the minimum number of writes and ++ also to minimise the read-modify-write activity (which generally ++ indicates a lack of clarity in the use model). ++ ++ Registers which are programmed in this module are listed below ++ together with the method of access. Care must be taken to ensure ++ remain adequate if the register spec changes. ++ ++ All 128bits programmed ++ FALCON_BUFFER_TBL_HALF ++ RX_FILTER_TBL ++ TX_DESC_PTR_TBL ++ RX_DESC_PTR_TBL ++ DRV_EV_REG ++ ++ All 64bits programmed ++ FALCON_BUFFER_TBL_FULL ++ ++ 32 bits are programmed (UNLOCKED) ++ EVQ_RPTR_REG ++ ++ Low 64bits programmed remainder are written with a random number ++ RX_DC_CFG_REG ++ TX_DC_CFG_REG ++ SRM_RX_DC_CFG_REG ++ SRM_TX_DC_CFG_REG ++ BUF_TBL_CFG_REG ++ BUF_TBL_UPD_REG ++ SRM_UPD_EVQ_REG ++ EVQ_PTR_TBL ++ TIMER_CMD_REG ++ TX_PACE_TBL ++ FATAL_INTR_REG ++ INT_EN_REG (When enabling interrupts) ++ TX_FLUSH_DESCQ_REG ++ RX_FLUSH_DESCQ ++ ++ Read Modify Write on low 32bits remainder are written with a random number ++ INT_EN_REG (When sending a driver interrupt) ++ DRIVER_REGX ++ ++ Read Modify Write on low 64bits remainder are written with a random number ++ SRM_CFG_REG_OFST ++ RX_CFG_REG_OFST ++ RX_FILTER_CTL_REG ++ ++ Read Modify Write on full 128bits ++ TXDP_RESERVED_REG (aka TXDP_UNDOCUMENTED) ++ TX_CFG_REG ++ ++*/ ++ ++ ++/*---------------------------------------------------------------------------- ++ * ++ * DMAQ low-level register interface ++ * ++ *---------------------------------------------------------------------------*/ ++ ++static unsigned dmaq_sizes[] = { ++ 512, ++ EFHW_1K, ++ EFHW_2K, ++ EFHW_4K, ++}; ++ ++#define N_DMAQ_SIZES (sizeof(dmaq_sizes) / sizeof(dmaq_sizes[0])) ++ ++static inline ulong falcon_dma_tx_q_offset(struct efhw_nic *nic, unsigned dmaq) ++{ ++ EFHW_ASSERT(dmaq < nic->num_dmaqs); ++ return TX_DESC_PTR_TBL_OFST + dmaq * FALCON_REGISTER128; ++} ++ ++static inline uint falcon_dma_tx_q_size_index(uint dmaq_size) ++{ ++ uint i; ++ ++ /* size must be one of the various options, otherwise we assert */ ++ for (i = 0; i < N_DMAQ_SIZES; i++) { ++ if (dmaq_size == dmaq_sizes[i]) ++ break; ++ } ++ EFHW_ASSERT(i < N_DMAQ_SIZES); ++ return i; ++} ++ ++static void ++falcon_dmaq_tx_q_init(struct efhw_nic *nic, ++ uint dmaq, uint evq_id, uint own_id, ++ uint tag, uint dmaq_size, uint buf_idx, uint flags) ++{ ++ FALCON_LOCK_DECL; ++ uint index, desc_type; ++ uint64_t val1, val2, val3; ++ ulong offset; ++ volatile char __iomem *efhw_kva = EFHW_KVA(nic); ++ ++ /* Q attributes */ ++ int iscsi_hdig_en = ((flags & EFHW_VI_ISCSI_TX_HDIG_EN) != 0); ++ int iscsi_ddig_en = ((flags & EFHW_VI_ISCSI_TX_DDIG_EN) != 0); ++ int csum_ip_dis = ((flags & EFHW_VI_TX_IP_CSUM_DIS) != 0); ++ int csum_tcp_dis = ((flags & EFHW_VI_TX_TCPUDP_CSUM_DIS) != 0); ++ int non_ip_drop_dis = ((flags & EFHW_VI_TX_TCPUDP_ONLY) == 0); ++ ++ /* initialise the TX descriptor queue pointer table */ ++ ++ /* NB physical vs buffer addressing is determined by the Queue ID. */ ++ ++ offset = falcon_dma_tx_q_offset(nic, dmaq); ++ index = falcon_dma_tx_q_size_index(dmaq_size); ++ ++ /* allow VI flag to override this queue's descriptor type */ ++ desc_type = (flags & EFHW_VI_TX_PHYS_ADDR_EN) ? 0 : 1; ++ ++ /* bug9403: It is dangerous to allow buffer-addressed queues to ++ * have owner_id=0. */ ++ EFHW_ASSERT((own_id > 0) || desc_type == 0); ++ ++ /* dword 1 */ ++ __DWCHCK(TX_DESCQ_FLUSH_LBN, TX_DESCQ_FLUSH_WIDTH); ++ __DWCHCK(TX_DESCQ_TYPE_LBN, TX_DESCQ_TYPE_WIDTH); ++ __DWCHCK(TX_DESCQ_SIZE_LBN, TX_DESCQ_SIZE_WIDTH); ++ __DWCHCK(TX_DESCQ_LABEL_LBN, TX_DESCQ_LABEL_WIDTH); ++ __DWCHCK(TX_DESCQ_OWNER_ID_LBN, TX_DESCQ_OWNER_ID_WIDTH); ++ ++ __LWCHK(TX_DESCQ_EVQ_ID_LBN, TX_DESCQ_EVQ_ID_WIDTH); ++ ++ __RANGECHCK(1, TX_DESCQ_FLUSH_WIDTH); ++ __RANGECHCK(desc_type, TX_DESCQ_TYPE_WIDTH); ++ __RANGECHCK(index, TX_DESCQ_SIZE_WIDTH); ++ __RANGECHCK(tag, TX_DESCQ_LABEL_WIDTH); ++ __RANGECHCK(own_id, TX_DESCQ_OWNER_ID_WIDTH); ++ __RANGECHCK(evq_id, TX_DESCQ_EVQ_ID_WIDTH); ++ ++ val1 = ((desc_type << TX_DESCQ_TYPE_LBN) | ++ (index << TX_DESCQ_SIZE_LBN) | ++ (tag << TX_DESCQ_LABEL_LBN) | ++ (own_id << TX_DESCQ_OWNER_ID_LBN) | ++ (__LOW(evq_id, TX_DESCQ_EVQ_ID_LBN, TX_DESCQ_EVQ_ID_WIDTH))); ++ ++ /* dword 2 */ ++ __DW2CHCK(TX_DESCQ_BUF_BASE_ID_LBN, TX_DESCQ_BUF_BASE_ID_WIDTH); ++ __RANGECHCK(buf_idx, TX_DESCQ_BUF_BASE_ID_WIDTH); ++ ++ val2 = ((__HIGH(evq_id, TX_DESCQ_EVQ_ID_LBN, TX_DESCQ_EVQ_ID_WIDTH)) | ++ (buf_idx << __DW2(TX_DESCQ_BUF_BASE_ID_LBN))); ++ ++ /* dword 3 */ ++ __DW3CHCK(TX_ISCSI_HDIG_EN_LBN, TX_ISCSI_HDIG_EN_WIDTH); ++ __DW3CHCK(TX_ISCSI_DDIG_EN_LBN, TX_ISCSI_DDIG_EN_WIDTH); ++ __RANGECHCK(iscsi_hdig_en, TX_ISCSI_HDIG_EN_WIDTH); ++ __RANGECHCK(iscsi_ddig_en, TX_ISCSI_DDIG_EN_WIDTH); ++ ++ val3 = ((iscsi_hdig_en << __DW3(TX_ISCSI_HDIG_EN_LBN)) | ++ (iscsi_ddig_en << __DW3(TX_ISCSI_DDIG_EN_LBN)) | ++ (1 << __DW3(TX_DESCQ_EN_LBN))); /* queue enable bit */ ++ ++ switch (nic->devtype.variant) { ++ case 'B': ++ __DW3CHCK(TX_NON_IP_DROP_DIS_B0_LBN, ++ TX_NON_IP_DROP_DIS_B0_WIDTH); ++ __DW3CHCK(TX_IP_CHKSM_DIS_B0_LBN, TX_IP_CHKSM_DIS_B0_WIDTH); ++ __DW3CHCK(TX_TCP_CHKSM_DIS_B0_LBN, TX_TCP_CHKSM_DIS_B0_WIDTH); ++ ++ val3 |= ((non_ip_drop_dis << __DW3(TX_NON_IP_DROP_DIS_B0_LBN))| ++ (csum_ip_dis << __DW3(TX_IP_CHKSM_DIS_B0_LBN)) | ++ (csum_tcp_dis << __DW3(TX_TCP_CHKSM_DIS_B0_LBN))); ++ break; ++ case 'A': ++ if (csum_ip_dis || csum_tcp_dis || !non_ip_drop_dis) ++ EFHW_WARN ++ ("%s: bad settings for A1 csum_ip_dis=%d " ++ "csum_tcp_dis=%d non_ip_drop_dis=%d", ++ __func__, csum_ip_dis, ++ csum_tcp_dis, non_ip_drop_dis); ++ break; ++ default: ++ EFHW_ASSERT(0); ++ break; ++ } ++ ++ EFHW_TRACE("%s: txq %x evq %u tag %x id %x buf %x " ++ "%x:%x:%x->%" PRIx64 ":%" PRIx64 ":%" PRIx64, ++ __func__, ++ dmaq, evq_id, tag, own_id, buf_idx, dmaq_size, ++ iscsi_hdig_en, iscsi_ddig_en, val1, val2, val3); ++ ++ /* Falcon requires 128 bit atomic access for this register */ ++ FALCON_LOCK_LOCK(nic); ++ falcon_write_qq(efhw_kva + offset, ((val2 << 32) | val1), val3); ++ mmiowb(); ++ FALCON_LOCK_UNLOCK(nic); ++ return; ++} ++ ++static inline ulong ++falcon_dma_rx_q_offset(struct efhw_nic *nic, unsigned dmaq) ++{ ++ EFHW_ASSERT(dmaq < nic->num_dmaqs); ++ return RX_DESC_PTR_TBL_OFST + dmaq * FALCON_REGISTER128; ++} ++ ++static void ++falcon_dmaq_rx_q_init(struct efhw_nic *nic, ++ uint dmaq, uint evq_id, uint own_id, ++ uint tag, uint dmaq_size, uint buf_idx, uint flags) ++{ ++ FALCON_LOCK_DECL; ++ uint i, desc_type = 1; ++ uint64_t val1, val2, val3; ++ ulong offset; ++ volatile char __iomem *efhw_kva = EFHW_KVA(nic); ++ ++ /* Q attributes */ ++#if BUG5762_WORKAROUND ++ int jumbo = 1; /* Queues must not have mixed types */ ++#else ++ int jumbo = ((flags & EFHW_VI_JUMBO_EN) != 0); ++#endif ++ int iscsi_hdig_en = ((flags & EFHW_VI_ISCSI_RX_HDIG_EN) != 0); ++ int iscsi_ddig_en = ((flags & EFHW_VI_ISCSI_RX_DDIG_EN) != 0); ++ ++ /* initialise the TX descriptor queue pointer table */ ++ offset = falcon_dma_rx_q_offset(nic, dmaq); ++ ++ /* size must be one of the various options, otherwise we assert */ ++ for (i = 0; i < N_DMAQ_SIZES; i++) { ++ if (dmaq_size == dmaq_sizes[i]) ++ break; ++ } ++ EFHW_ASSERT(i < N_DMAQ_SIZES); ++ ++ /* allow VI flag to override this queue's descriptor type */ ++ desc_type = (flags & EFHW_VI_RX_PHYS_ADDR_EN) ? 0 : 1; ++ ++ /* bug9403: It is dangerous to allow buffer-addressed queues to have ++ * owner_id=0 */ ++ EFHW_ASSERT((own_id > 0) || desc_type == 0); ++ ++ /* dword 1 */ ++ __DWCHCK(RX_DESCQ_EN_LBN, RX_DESCQ_EN_WIDTH); ++ __DWCHCK(RX_DESCQ_JUMBO_LBN, RX_DESCQ_JUMBO_WIDTH); ++ __DWCHCK(RX_DESCQ_TYPE_LBN, RX_DESCQ_TYPE_WIDTH); ++ __DWCHCK(RX_DESCQ_SIZE_LBN, RX_DESCQ_SIZE_WIDTH); ++ __DWCHCK(RX_DESCQ_LABEL_LBN, RX_DESCQ_LABEL_WIDTH); ++ __DWCHCK(RX_DESCQ_OWNER_ID_LBN, RX_DESCQ_OWNER_ID_WIDTH); ++ ++ __LWCHK(RX_DESCQ_EVQ_ID_LBN, RX_DESCQ_EVQ_ID_WIDTH); ++ ++ __RANGECHCK(1, RX_DESCQ_EN_WIDTH); ++ __RANGECHCK(jumbo, RX_DESCQ_JUMBO_WIDTH); ++ __RANGECHCK(desc_type, RX_DESCQ_TYPE_WIDTH); ++ __RANGECHCK(i, RX_DESCQ_SIZE_WIDTH); ++ __RANGECHCK(tag, RX_DESCQ_LABEL_WIDTH); ++ __RANGECHCK(own_id, RX_DESCQ_OWNER_ID_WIDTH); ++ __RANGECHCK(evq_id, RX_DESCQ_EVQ_ID_WIDTH); ++ ++ val1 = ((1 << RX_DESCQ_EN_LBN) | ++ (jumbo << RX_DESCQ_JUMBO_LBN) | ++ (desc_type << RX_DESCQ_TYPE_LBN) | ++ (i << RX_DESCQ_SIZE_LBN) | ++ (tag << RX_DESCQ_LABEL_LBN) | ++ (own_id << RX_DESCQ_OWNER_ID_LBN) | ++ (__LOW(evq_id, RX_DESCQ_EVQ_ID_LBN, RX_DESCQ_EVQ_ID_WIDTH))); ++ ++ /* dword 2 */ ++ __DW2CHCK(RX_DESCQ_BUF_BASE_ID_LBN, RX_DESCQ_BUF_BASE_ID_WIDTH); ++ __RANGECHCK(buf_idx, RX_DESCQ_BUF_BASE_ID_WIDTH); ++ ++ val2 = ((__HIGH(evq_id, RX_DESCQ_EVQ_ID_LBN, RX_DESCQ_EVQ_ID_WIDTH)) | ++ (buf_idx << __DW2(RX_DESCQ_BUF_BASE_ID_LBN))); ++ ++ /* dword 3 */ ++ __DW3CHCK(RX_ISCSI_HDIG_EN_LBN, RX_ISCSI_HDIG_EN_WIDTH); ++ __DW3CHCK(RX_ISCSI_DDIG_EN_LBN, RX_ISCSI_DDIG_EN_WIDTH); ++ __RANGECHCK(iscsi_hdig_en, RX_ISCSI_HDIG_EN_WIDTH); ++ __RANGECHCK(iscsi_ddig_en, RX_ISCSI_DDIG_EN_WIDTH); ++ ++ val3 = (iscsi_hdig_en << __DW3(RX_ISCSI_HDIG_EN_LBN)) | ++ (iscsi_ddig_en << __DW3(RX_ISCSI_DDIG_EN_LBN)); ++ ++ EFHW_TRACE("%s: rxq %x evq %u tag %x id %x buf %x %s " ++ "%x:%x:%x -> %" PRIx64 ":%" PRIx64 ":%" PRIx64, ++ __func__, ++ dmaq, evq_id, tag, own_id, buf_idx, ++ jumbo ? "jumbo" : "normal", dmaq_size, ++ iscsi_hdig_en, iscsi_ddig_en, val1, val2, val3); ++ ++ /* Falcon requires 128 bit atomic access for this register */ ++ FALCON_LOCK_LOCK(nic); ++ falcon_write_qq(efhw_kva + offset, ((val2 << 32) | val1), val3); ++ mmiowb(); ++ FALCON_LOCK_UNLOCK(nic); ++ return; ++} ++ ++static void falcon_dmaq_tx_q_disable(struct efhw_nic *nic, uint dmaq) ++{ ++ FALCON_LOCK_DECL; ++ uint64_t val1, val2, val3; ++ ulong offset; ++ volatile char __iomem *efhw_kva = EFHW_KVA(nic); ++ ++ /* initialise the TX descriptor queue pointer table */ ++ ++ offset = falcon_dma_tx_q_offset(nic, dmaq); ++ ++ /* dword 1 */ ++ __DWCHCK(TX_DESCQ_TYPE_LBN, TX_DESCQ_TYPE_WIDTH); ++ ++ val1 = ((uint64_t) 1 << TX_DESCQ_TYPE_LBN); ++ ++ /* dword 2 */ ++ val2 = 0; ++ ++ /* dword 3 */ ++ val3 = (0 << __DW3(TX_DESCQ_EN_LBN)); /* queue enable bit */ ++ ++ EFHW_TRACE("%s: %x->%" PRIx64 ":%" PRIx64 ":%" PRIx64, ++ __func__, dmaq, val1, val2, val3); ++ ++ /* Falcon requires 128 bit atomic access for this register */ ++ FALCON_LOCK_LOCK(nic); ++ falcon_write_qq(efhw_kva + offset, ((val2 << 32) | val1), val3); ++ mmiowb(); ++ FALCON_LOCK_UNLOCK(nic); ++ return; ++} ++ ++static void falcon_dmaq_rx_q_disable(struct efhw_nic *nic, uint dmaq) ++{ ++ FALCON_LOCK_DECL; ++ uint64_t val1, val2, val3; ++ ulong offset; ++ volatile char __iomem *efhw_kva = EFHW_KVA(nic); ++ ++ /* initialise the TX descriptor queue pointer table */ ++ offset = falcon_dma_rx_q_offset(nic, dmaq); ++ ++ /* dword 1 */ ++ __DWCHCK(RX_DESCQ_EN_LBN, RX_DESCQ_EN_WIDTH); ++ __DWCHCK(RX_DESCQ_TYPE_LBN, RX_DESCQ_TYPE_WIDTH); ++ ++ val1 = ((0 << RX_DESCQ_EN_LBN) | (1 << RX_DESCQ_TYPE_LBN)); ++ ++ /* dword 2 */ ++ val2 = 0; ++ ++ /* dword 3 */ ++ val3 = 0; ++ ++ EFHW_TRACE("falcon_dmaq_rx_q_disable: %x->%" ++ PRIx64 ":%" PRIx64 ":%" PRIx64, ++ dmaq, val1, val2, val3); ++ ++ /* Falcon requires 128 bit atomic access for this register */ ++ FALCON_LOCK_LOCK(nic); ++ falcon_write_qq(efhw_kva + offset, ((val2 << 32) | val1), val3); ++ mmiowb(); ++ FALCON_LOCK_UNLOCK(nic); ++ return; ++} ++ ++ ++/*---------------------------------------------------------------------------- ++ * ++ * Buffer Table low-level register interface ++ * ++ *---------------------------------------------------------------------------*/ ++ ++/*! Convert a (potentially) 64-bit physical address to 32-bits. Every use ++** of this function is a place where we're not 64-bit clean. ++*/ ++static inline uint32_t dma_addr_to_u32(dma_addr_t addr) ++{ ++ /* Top bits had better be zero! */ ++ EFHW_ASSERT(addr == (addr & 0xffffffff)); ++ return (uint32_t) addr; ++} ++ ++static inline uint32_t ++falcon_nic_buffer_table_entry32_mk(dma_addr_t dma_addr, int own_id) ++{ ++ uint32_t dma_addr32 = FALCON_BUFFER_4K_PAGE(dma_addr_to_u32(dma_addr)); ++ ++ /* don't do this to me */ ++ EFHW_BUILD_ASSERT(BUF_ADR_HBUF_ODD_LBN == BUF_ADR_HBUF_EVEN_LBN + 32); ++ EFHW_BUILD_ASSERT(BUF_OWNER_ID_HBUF_ODD_LBN == ++ BUF_OWNER_ID_HBUF_EVEN_LBN + 32); ++ ++ EFHW_BUILD_ASSERT(BUF_OWNER_ID_HBUF_ODD_WIDTH == ++ BUF_OWNER_ID_HBUF_EVEN_WIDTH); ++ EFHW_BUILD_ASSERT(BUF_ADR_HBUF_ODD_WIDTH == BUF_ADR_HBUF_EVEN_WIDTH); ++ ++ __DWCHCK(BUF_ADR_HBUF_EVEN_LBN, BUF_ADR_HBUF_EVEN_WIDTH); ++ __DWCHCK(BUF_OWNER_ID_HBUF_EVEN_LBN, BUF_OWNER_ID_HBUF_EVEN_WIDTH); ++ ++ __RANGECHCK(dma_addr32, BUF_ADR_HBUF_EVEN_WIDTH); ++ __RANGECHCK(own_id, BUF_OWNER_ID_HBUF_EVEN_WIDTH); ++ ++ return (dma_addr32 << BUF_ADR_HBUF_EVEN_LBN) | ++ (own_id << BUF_OWNER_ID_HBUF_EVEN_LBN); ++} ++ ++static inline uint64_t ++falcon_nic_buffer_table_entry64_mk(dma_addr_t dma_addr, ++ int bufsz, /* bytes */ ++ int region, int own_id) ++{ ++ __DW2CHCK(IP_DAT_BUF_SIZE_LBN, IP_DAT_BUF_SIZE_WIDTH); ++ __DW2CHCK(BUF_ADR_REGION_LBN, BUF_ADR_REGION_WIDTH); ++ __LWCHK(BUF_ADR_FBUF_LBN, BUF_ADR_FBUF_WIDTH); ++ __DWCHCK(BUF_OWNER_ID_FBUF_LBN, BUF_OWNER_ID_FBUF_WIDTH); ++ ++ EFHW_ASSERT((bufsz == EFHW_4K) || (bufsz == EFHW_8K)); ++ ++ dma_addr = (dma_addr >> 12) & __FALCON_MASK64(BUF_ADR_FBUF_WIDTH); ++ ++ __RANGECHCK(dma_addr, BUF_ADR_FBUF_WIDTH); ++ __RANGECHCK(1, IP_DAT_BUF_SIZE_WIDTH); ++ __RANGECHCK(region, BUF_ADR_REGION_WIDTH); ++ __RANGECHCK(own_id, BUF_OWNER_ID_FBUF_WIDTH); ++ ++ return ((uint64_t) (bufsz == EFHW_8K) << IP_DAT_BUF_SIZE_LBN) | ++ ((uint64_t) region << BUF_ADR_REGION_LBN) | ++ ((uint64_t) dma_addr << BUF_ADR_FBUF_LBN) | ++ ((uint64_t) own_id << BUF_OWNER_ID_FBUF_LBN); ++} ++ ++static inline void ++_falcon_nic_buffer_table_set32(struct efhw_nic *nic, ++ dma_addr_t dma_addr, uint bufsz, ++ uint region, /* not used */ ++ int own_id, int buffer_id) ++{ ++ /* programming the half table needs to be done in pairs. */ ++ uint64_t entry, val, shift; ++ volatile char __iomem *efhw_kva = EFHW_KVA(nic); ++ volatile char __iomem *offset; ++ ++ EFHW_BUILD_ASSERT(BUF_ADR_HBUF_ODD_LBN == BUF_ADR_HBUF_EVEN_LBN + 32); ++ EFHW_BUILD_ASSERT(BUF_OWNER_ID_HBUF_ODD_LBN == ++ BUF_OWNER_ID_HBUF_EVEN_LBN + 32); ++ ++ shift = (buffer_id & 1) ? 32 : 0; ++ ++ offset = (efhw_kva + BUF_HALF_TBL_OFST + ++ ((buffer_id & ~1) * FALCON_BUFFER_TBL_HALF_BYTES)); ++ ++ entry = falcon_nic_buffer_table_entry32_mk(dma_addr_to_u32(dma_addr), ++ own_id); ++ ++#if FALCON_USE_SHADOW_BUFFER_TABLE ++ val = _falcon_buffer_table[buffer_id & ~1]; ++#else ++ /* This will not work unless we've completed ++ * the buffer table updates */ ++ falcon_read_q(offset, &val); ++#endif ++ val &= ~(((uint64_t) 0xffffffff) << shift); ++ val |= (entry << shift); ++ ++ EFHW_TRACE("%s[%x]: %lx:%x:%" PRIx64 "->%x = %" ++ PRIx64, __func__, buffer_id, (unsigned long) dma_addr, ++ own_id, entry, (unsigned)(offset - efhw_kva), val); ++ ++ /* Falcon requires that access to this register is serialised */ ++ falcon_write_q(offset, val); ++ ++ /* NB. No mmiowb(). Caller should do that e.g by calling commit */ ++ ++#if FALCON_USE_SHADOW_BUFFER_TABLE ++ _falcon_buffer_table[buffer_id & ~1] = val; ++#endif ++ ++ /* Confirm the entry if the event queues haven't been set up. */ ++ if (!nic->irq_handler) { ++ uint64_t new_val; ++ int count = 0; ++ while (1) { ++ mmiowb(); ++ falcon_read_q(offset, &new_val); ++ if (new_val == val) ++ break; ++ count++; ++ if (count > 1000) { ++ EFHW_WARN("%s: poll Timeout", __func__); ++ break; ++ } ++ udelay(1); ++ } ++ } ++} ++ ++static inline void ++_falcon_nic_buffer_table_set64(struct efhw_nic *nic, ++ dma_addr_t dma_addr, uint bufsz, ++ uint region, int own_id, int buffer_id) ++{ ++ volatile char __iomem *offset; ++ uint64_t entry; ++ volatile char __iomem *efhw_kva = EFHW_KVA(nic); ++ ++ EFHW_ASSERT(region < FALCON_REGION_NUM); ++ ++ EFHW_ASSERT((bufsz == EFHW_4K) || ++ (bufsz == EFHW_8K && FALCON_BUFFER_TABLE_FULL_MODE)); ++ ++ offset = (efhw_kva + BUF_FULL_TBL_OFST + ++ (buffer_id * FALCON_BUFFER_TBL_FULL_BYTES)); ++ ++ entry = falcon_nic_buffer_table_entry64_mk(dma_addr, bufsz, region, ++ own_id); ++ ++ EFHW_TRACE("%s[%x]: %lx:bufsz=%x:region=%x:ownid=%x", ++ __func__, buffer_id, (unsigned long) dma_addr, bufsz, ++ region, own_id); ++ ++ EFHW_TRACE("%s: BUF[%x]:NIC[%x]->%" PRIx64, ++ __func__, buffer_id, ++ (unsigned int)(offset - efhw_kva), entry); ++ ++ /* Falcon requires that access to this register is serialised */ ++ falcon_write_q(offset, entry); ++ ++ /* NB. No mmiowb(). Caller should do that e.g by calling commit */ ++ ++ /* Confirm the entry if the event queues haven't been set up. */ ++ if (!nic->irq_handler) { ++ uint64_t new_entry; ++ int count = 0; ++ while (1) { ++ mmiowb(); ++ falcon_read_q(offset, &new_entry); ++ if (new_entry == entry) ++ return; ++ count++; ++ if (count > 1000) { ++ EFHW_WARN("%s: poll Timeout waiting for " ++ "value %"PRIx64 ++ " (last was %"PRIx64")", ++ __func__, entry, new_entry); ++ break; ++ } ++ udelay(1); ++ } ++ } ++} ++ ++#if FALCON_BUFFER_TABLE_FULL_MODE ++#define _falcon_nic_buffer_table_set _falcon_nic_buffer_table_set64 ++#else ++#define _falcon_nic_buffer_table_set _falcon_nic_buffer_table_set32 ++#endif ++ ++static inline void _falcon_nic_buffer_table_commit(struct efhw_nic *nic) ++{ ++ /* MUST be called holding the FALCON_LOCK */ ++ volatile char __iomem *efhw_kva = EFHW_KVA(nic); ++ uint64_t cmd; ++ ++ EFHW_BUILD_ASSERT(BUF_TBL_UPD_REG_KER_OFST == BUF_TBL_UPD_REG_OFST); ++ ++ __DW2CHCK(BUF_UPD_CMD_LBN, BUF_UPD_CMD_WIDTH); ++ __RANGECHCK(1, BUF_UPD_CMD_WIDTH); ++ ++ cmd = ((uint64_t) 1 << BUF_UPD_CMD_LBN); ++ ++ /* Falcon requires 128 bit atomic access for this register */ ++ falcon_write_qq(efhw_kva + BUF_TBL_UPD_REG_OFST, ++ cmd, FALCON_ATOMIC_UPD_REG); ++ mmiowb(); ++ ++ nic->buf_commit_outstanding++; ++ EFHW_TRACE("COMMIT REQ out=%d", nic->buf_commit_outstanding); ++} ++ ++static void falcon_nic_buffer_table_commit(struct efhw_nic *nic) ++{ ++ /* nothing to do */ ++} ++ ++static inline void ++_falcon_nic_buffer_table_clear(struct efhw_nic *nic, int buffer_id, int num) ++{ ++ uint64_t cmd; ++ uint64_t start_id = buffer_id; ++ uint64_t end_id = buffer_id + num - 1; ++ volatile char __iomem *efhw_kva = EFHW_KVA(nic); ++ ++ volatile char __iomem *offset = (efhw_kva + BUF_TBL_UPD_REG_OFST); ++ ++ EFHW_BUILD_ASSERT(BUF_TBL_UPD_REG_KER_OFST == BUF_TBL_UPD_REG_OFST); ++ ++#if !FALCON_BUFFER_TABLE_FULL_MODE ++ /* buffer_ids in half buffer mode reference pairs of buffers */ ++ EFHW_ASSERT(buffer_id % 1 == 0); ++ EFHW_ASSERT(num % 1 == 0); ++ start_id = start_id >> 1; ++ end_id = end_id >> 1; ++#endif ++ ++ EFHW_ASSERT(num >= 1); ++ ++ __DWCHCK(BUF_CLR_START_ID_LBN, BUF_CLR_START_ID_WIDTH); ++ __DW2CHCK(BUF_CLR_END_ID_LBN, BUF_CLR_END_ID_WIDTH); ++ ++ __DW2CHCK(BUF_CLR_CMD_LBN, BUF_CLR_CMD_WIDTH); ++ __RANGECHCK(1, BUF_CLR_CMD_WIDTH); ++ ++ __RANGECHCK(start_id, BUF_CLR_START_ID_WIDTH); ++ __RANGECHCK(end_id, BUF_CLR_END_ID_WIDTH); ++ ++ cmd = (((uint64_t) 1 << BUF_CLR_CMD_LBN) | ++ (start_id << BUF_CLR_START_ID_LBN) | ++ (end_id << BUF_CLR_END_ID_LBN)); ++ ++ /* Falcon requires 128 bit atomic access for this register */ ++ falcon_write_qq(offset, cmd, FALCON_ATOMIC_UPD_REG); ++ mmiowb(); ++ ++ nic->buf_commit_outstanding++; ++ EFHW_TRACE("COMMIT CLEAR out=%d", nic->buf_commit_outstanding); ++} ++ ++/*---------------------------------------------------------------------------- ++ * ++ * Events low-level register interface ++ * ++ *---------------------------------------------------------------------------*/ ++ ++static unsigned eventq_sizes[] = { ++ 512, ++ EFHW_1K, ++ EFHW_2K, ++ EFHW_4K, ++ EFHW_8K, ++ EFHW_16K, ++ EFHW_32K ++}; ++ ++#define N_EVENTQ_SIZES (sizeof(eventq_sizes) / sizeof(eventq_sizes[0])) ++ ++static inline void falcon_nic_srm_upd_evq(struct efhw_nic *nic, int evq) ++{ ++ /* set up the eventq which will receive events from the SRAM module. ++ * i.e buffer table updates and clears, TX and RX aperture table ++ * updates */ ++ ++ FALCON_LOCK_DECL; ++ volatile char __iomem *efhw_kva = EFHW_KVA(nic); ++ ++ EFHW_BUILD_ASSERT(SRM_UPD_EVQ_REG_OFST == SRM_UPD_EVQ_REG_KER_OFST); ++ ++ __DWCHCK(SRM_UPD_EVQ_ID_LBN, SRM_UPD_EVQ_ID_WIDTH); ++ __RANGECHCK(evq, SRM_UPD_EVQ_ID_WIDTH); ++ ++ /* Falcon requires 128 bit atomic access for this register */ ++ FALCON_LOCK_LOCK(nic); ++ falcon_write_qq(efhw_kva + SRM_UPD_EVQ_REG_OFST, ++ ((uint64_t) evq << SRM_UPD_EVQ_ID_LBN), ++ FALCON_ATOMIC_SRPM_UDP_EVQ_REG); ++ mmiowb(); ++ FALCON_LOCK_UNLOCK(nic); ++} ++ ++static void ++falcon_nic_evq_ptr_tbl(struct efhw_nic *nic, ++ uint evq, /* evq id */ ++ uint enable, /* 1 to enable, 0 to disable */ ++ uint buf_base_id,/* Buffer table base for EVQ */ ++ uint evq_size /* Number of events */) ++{ ++ FALCON_LOCK_DECL; ++ uint i, val; ++ ulong offset; ++ volatile char __iomem *efhw_kva = EFHW_KVA(nic); ++ ++ /* size must be one of the various options, otherwise we assert */ ++ for (i = 0; i < N_EVENTQ_SIZES; i++) { ++ if (evq_size <= eventq_sizes[i]) ++ break; ++ } ++ EFHW_ASSERT(i < N_EVENTQ_SIZES); ++ ++ __DWCHCK(EVQ_BUF_BASE_ID_LBN, EVQ_BUF_BASE_ID_WIDTH); ++ __DWCHCK(EVQ_SIZE_LBN, EVQ_SIZE_WIDTH); ++ __DWCHCK(EVQ_EN_LBN, EVQ_EN_WIDTH); ++ ++ __RANGECHCK(i, EVQ_SIZE_WIDTH); ++ __RANGECHCK(buf_base_id, EVQ_BUF_BASE_ID_WIDTH); ++ __RANGECHCK(1, EVQ_EN_WIDTH); ++ ++ /* if !enable then only evq needs to be correct, although valid ++ * values need to be passed in for other arguments to prevent ++ * assertions */ ++ ++ val = ((i << EVQ_SIZE_LBN) | (buf_base_id << EVQ_BUF_BASE_ID_LBN) | ++ (enable ? (1 << EVQ_EN_LBN) : 0)); ++ ++ EFHW_ASSERT(evq < nic->num_evqs); ++ ++ offset = EVQ_PTR_TBL_CHAR_OFST; ++ offset += evq * FALCON_REGISTER128; ++ ++ EFHW_TRACE("%s: evq %u en=%x:buf=%x:size=%x->%x at %lx", ++ __func__, evq, enable, buf_base_id, evq_size, val, ++ offset); ++ ++ /* Falcon requires 128 bit atomic access for this register */ ++ FALCON_LOCK_LOCK(nic); ++ falcon_write_qq(efhw_kva + offset, val, FALCON_ATOMIC_PTR_TBL_REG); ++ mmiowb(); ++ FALCON_LOCK_UNLOCK(nic); ++ ++ /* caller must wait for an update done event before writing any more ++ table entries */ ++ ++ return; ++} ++ ++void ++falcon_nic_evq_ack(struct efhw_nic *nic, ++ uint evq, /* evq id */ ++ uint rptr, /* new read pointer update */ ++ bool wakeup /* request a wakeup event if ptr's != */ ++ ) ++{ ++ uint val; ++ ulong offset; ++ volatile char __iomem *efhw_kva = EFHW_KVA(nic); ++ ++ EFHW_BUILD_ASSERT(FALCON_EVQ_CHAR == 4); ++ ++ __DWCHCK(EVQ_RPTR_LBN, EVQ_RPTR_WIDTH); ++ __RANGECHCK(rptr, EVQ_RPTR_WIDTH); ++ ++ val = (rptr << EVQ_RPTR_LBN); ++ ++ EFHW_ASSERT(evq < nic->num_evqs); ++ ++ if (evq < FALCON_EVQ_CHAR) { ++ offset = EVQ_RPTR_REG_KER_OFST; ++ offset += evq * FALCON_REGISTER128; ++ ++ EFHW_ASSERT(!wakeup); /* don't try this at home */ ++ } else { ++ offset = EVQ_RPTR_REG_OFST + (FALCON_EVQ_CHAR * ++ FALCON_REGISTER128); ++ offset += (evq - FALCON_EVQ_CHAR) * FALCON_REGISTER128; ++ ++ /* nothing to do for interruptless event queues which do ++ * not want a wakeup */ ++ if (evq != FALCON_EVQ_CHAR && !wakeup) ++ return; ++ } ++ ++ EFHW_TRACE("%s: %x %x %x->%x", __func__, evq, rptr, wakeup, val); ++ ++ writel(val, efhw_kva + offset); ++ mmiowb(); ++} ++ ++/*---------------------------------------------------------------------------*/ ++ ++static inline void ++falcon_drv_ev(struct efhw_nic *nic, uint64_t data, uint qid) ++{ ++ FALCON_LOCK_DECL; ++ volatile char __iomem *efhw_kva = EFHW_KVA(nic); ++ ++ /* send an event from one driver to the other */ ++ EFHW_BUILD_ASSERT(DRV_EV_REG_KER_OFST == DRV_EV_REG_OFST); ++ EFHW_BUILD_ASSERT(DRV_EV_DATA_LBN == 0); ++ EFHW_BUILD_ASSERT(DRV_EV_DATA_WIDTH == 64); ++ EFHW_BUILD_ASSERT(DRV_EV_QID_LBN == 64); ++ EFHW_BUILD_ASSERT(DRV_EV_QID_WIDTH == 12); ++ ++ FALCON_LOCK_LOCK(nic); ++ falcon_write_qq(efhw_kva + DRV_EV_REG_OFST, data, qid); ++ mmiowb(); ++ FALCON_LOCK_UNLOCK(nic); ++} ++ ++_DEBUG_SYM_ void ++falcon_ab_timer_tbl_set(struct efhw_nic *nic, ++ uint evq, /* timer id */ ++ uint mode, /* mode bits */ ++ uint countdown /* counting value to set */) ++{ ++ FALCON_LOCK_DECL; ++ uint val; ++ ulong offset; ++ volatile char __iomem *efhw_kva = EFHW_KVA(nic); ++ ++ EFHW_BUILD_ASSERT(TIMER_VAL_LBN == 0); ++ ++ __DWCHCK(TIMER_MODE_LBN, TIMER_MODE_WIDTH); ++ __DWCHCK(TIMER_VAL_LBN, TIMER_VAL_WIDTH); ++ ++ __RANGECHCK(mode, TIMER_MODE_WIDTH); ++ __RANGECHCK(countdown, TIMER_VAL_WIDTH); ++ ++ val = ((mode << TIMER_MODE_LBN) | (countdown << TIMER_VAL_LBN)); ++ ++ if (evq < FALCON_EVQ_CHAR) { ++ offset = TIMER_CMD_REG_KER_OFST; ++ offset += evq * EFHW_8K; /* PAGE mapped register */ ++ } else { ++ offset = TIMER_TBL_OFST; ++ offset += evq * FALCON_REGISTER128; ++ } ++ EFHW_ASSERT(evq < nic->num_evqs); ++ ++ EFHW_TRACE("%s: evq %u mode %x (%s) time %x -> %08x", ++ __func__, evq, mode, ++ mode == 0 ? "DISABLE" : ++ mode == 1 ? "IMMED" : ++ mode == 2 ? (evq < 5 ? "HOLDOFF" : "RX_TRIG") : ++ "", countdown, val); ++ ++ /* Falcon requires 128 bit atomic access for this register when ++ * accessed from the driver. User access to timers is paged mapped ++ */ ++ FALCON_LOCK_LOCK(nic); ++ falcon_write_qq(efhw_kva + offset, val, FALCON_ATOMIC_TIMER_CMD_REG); ++ mmiowb(); ++ FALCON_LOCK_UNLOCK(nic); ++ return; ++} ++ ++ ++/*-------------------------------------------------------------------- ++ * ++ * Rate pacing - Low level interface ++ * ++ *--------------------------------------------------------------------*/ ++void falcon_nic_pace(struct efhw_nic *nic, uint dmaq, uint pace) ++{ ++ /* Pace specified in 2^(units of microseconds). This is the minimum ++ additional delay imposed over and above the IPG. ++ ++ Pacing only available on the virtual interfaces ++ */ ++ FALCON_LOCK_DECL; ++ volatile char __iomem *efhw_kva = EFHW_KVA(nic); ++ ulong offset; ++ ++ if (pace > 20) ++ pace = 20; /* maxm supported value */ ++ ++ __DWCHCK(TX_PACE_LBN, TX_PACE_WIDTH); ++ __RANGECHCK(pace, TX_PACE_WIDTH); ++ ++ switch (nic->devtype.variant) { ++ case 'A': ++ EFHW_ASSERT(dmaq >= TX_PACE_TBL_FIRST_QUEUE_A1); ++ offset = TX_PACE_TBL_A1_OFST; ++ offset += (dmaq - TX_PACE_TBL_FIRST_QUEUE_A1) * 16; ++ break; ++ case 'B': ++ /* Would be nice to assert this, but as dmaq is unsigned and ++ * TX_PACE_TBL_FIRST_QUEUE_B0 is 0, it makes no sense ++ * EFHW_ASSERT(dmaq >= TX_PACE_TBL_FIRST_QUEUE_B0); ++ */ ++ offset = TX_PACE_TBL_B0_OFST; ++ offset += (dmaq - TX_PACE_TBL_FIRST_QUEUE_B0) * 16; ++ break; ++ default: ++ EFHW_ASSERT(0); ++ offset = 0; ++ break; ++ } ++ ++ /* Falcon requires 128 bit atomic access for this register */ ++ FALCON_LOCK_LOCK(nic); ++ falcon_write_qq(efhw_kva + offset, pace, FALCON_ATOMIC_PACE_REG); ++ mmiowb(); ++ FALCON_LOCK_UNLOCK(nic); ++ ++ EFHW_TRACE("%s: txq %d offset=%lx pace=2^%x", ++ __func__, dmaq, offset, pace); ++} ++ ++/*-------------------------------------------------------------------- ++ * ++ * Interrupt - Low level interface ++ * ++ *--------------------------------------------------------------------*/ ++ ++static void falcon_nic_handle_fatal_int(struct efhw_nic *nic) ++{ ++ FALCON_LOCK_DECL; ++ volatile char __iomem *offset; ++ volatile char __iomem *efhw_kva = EFHW_KVA(nic); ++ uint64_t val; ++ ++ offset = (efhw_kva + FATAL_INTR_REG_OFST); ++ ++ /* Falcon requires 32 bit atomic access for this register */ ++ FALCON_LOCK_LOCK(nic); ++ val = readl(offset); ++ FALCON_LOCK_UNLOCK(nic); ++ ++ /* ?? BUG3249 - need to disable illegal address interrupt */ ++ /* ?? BUG3114 - need to backport interrupt storm protection code */ ++ EFHW_ERR("fatal interrupt: %s%s%s%s%s%s%s%s%s%s%s%s[%" PRIx64 "]", ++ val & (1 << PCI_BUSERR_INT_CHAR_LBN) ? "PCI-bus-error " : "", ++ val & (1 << SRAM_OOB_INT_CHAR_LBN) ? "SRAM-oob " : "", ++ val & (1 << BUFID_OOB_INT_CHAR_LBN) ? "bufid-oob " : "", ++ val & (1 << MEM_PERR_INT_CHAR_LBN) ? "int-parity " : "", ++ val & (1 << RBUF_OWN_INT_CHAR_LBN) ? "rx-bufid-own " : "", ++ val & (1 << TBUF_OWN_INT_CHAR_LBN) ? "tx-bufid-own " : "", ++ val & (1 << RDESCQ_OWN_INT_CHAR_LBN) ? "rx-desc-own " : "", ++ val & (1 << TDESCQ_OWN_INT_CHAR_LBN) ? "tx-desc-own " : "", ++ val & (1 << EVQ_OWN_INT_CHAR_LBN) ? "evq-own " : "", ++ val & (1 << EVFF_OFLO_INT_CHAR_LBN) ? "evq-fifo " : "", ++ val & (1 << ILL_ADR_INT_CHAR_LBN) ? "ill-addr " : "", ++ val & (1 << SRM_PERR_INT_CHAR_LBN) ? "sram-parity " : "", val); ++} ++ ++static void falcon_nic_interrupt_hw_enable(struct efhw_nic *nic) ++{ ++ FALCON_LOCK_DECL; ++ uint val; ++ volatile char __iomem *offset; ++ volatile char __iomem *efhw_kva = EFHW_KVA(nic); ++ ++ EFHW_BUILD_ASSERT(DRV_INT_EN_CHAR_WIDTH == 1); ++ ++ if (nic->flags & NIC_FLAG_NO_INTERRUPT) ++ return; ++ ++ offset = (efhw_kva + INT_EN_REG_CHAR_OFST); ++ val = 1 << DRV_INT_EN_CHAR_LBN; ++ ++ EFHW_NOTICE("%s: %x -> %x", __func__, (int)(offset - efhw_kva), ++ val); ++ ++ /* Falcon requires 128 bit atomic access for this register */ ++ FALCON_LOCK_LOCK(nic); ++ falcon_write_qq(offset, val, FALCON_ATOMIC_INT_EN_REG); ++ mmiowb(); ++ FALCON_LOCK_UNLOCK(nic); ++} ++ ++static void falcon_nic_interrupt_hw_disable(struct efhw_nic *nic) ++{ ++ FALCON_LOCK_DECL; ++ volatile char __iomem *offset; ++ volatile char __iomem *efhw_kva = EFHW_KVA(nic); ++ ++ EFHW_BUILD_ASSERT(SRAM_PERR_INT_KER_WIDTH == 1); ++ EFHW_BUILD_ASSERT(DRV_INT_EN_KER_LBN == 0); ++ EFHW_BUILD_ASSERT(SRAM_PERR_INT_CHAR_WIDTH == 1); ++ EFHW_BUILD_ASSERT(DRV_INT_EN_CHAR_LBN == 0); ++ EFHW_BUILD_ASSERT(SRAM_PERR_INT_KER_LBN == SRAM_PERR_INT_CHAR_LBN); ++ EFHW_BUILD_ASSERT(DRV_INT_EN_KER_LBN == DRV_INT_EN_CHAR_LBN); ++ ++ if (nic->flags & NIC_FLAG_NO_INTERRUPT) ++ return; ++ ++ offset = (efhw_kva + INT_EN_REG_CHAR_OFST); ++ ++ EFHW_NOTICE("%s: %x -> 0", __func__, (int)(offset - efhw_kva)); ++ ++ /* Falcon requires 128 bit atomic access for this register */ ++ FALCON_LOCK_LOCK(nic); ++ falcon_write_qq(offset, 0, FALCON_ATOMIC_INT_EN_REG); ++ mmiowb(); ++ FALCON_LOCK_UNLOCK(nic); ++} ++ ++static void falcon_nic_irq_addr_set(struct efhw_nic *nic, dma_addr_t dma_addr) ++{ ++ FALCON_LOCK_DECL; ++ volatile char __iomem *offset; ++ volatile char __iomem *efhw_kva = EFHW_KVA(nic); ++ ++ offset = (efhw_kva + INT_ADR_REG_CHAR_OFST); ++ ++ EFHW_NOTICE("%s: %x -> " DMA_ADDR_T_FMT, __func__, ++ (int)(offset - efhw_kva), dma_addr); ++ ++ /* Falcon requires 128 bit atomic access for this register */ ++ FALCON_LOCK_LOCK(nic); ++ falcon_write_qq(offset, dma_addr, FALCON_ATOMIC_INT_ADR_REG); ++ mmiowb(); ++ FALCON_LOCK_UNLOCK(nic); ++} ++ ++ ++/*-------------------------------------------------------------------- ++ * ++ * RXDP - low level interface ++ * ++ *--------------------------------------------------------------------*/ ++ ++void ++falcon_nic_set_rx_usr_buf_size(struct efhw_nic *nic, int usr_buf_bytes) ++{ ++ FALCON_LOCK_DECL; ++ volatile char __iomem *efhw_kva = EFHW_KVA(nic); ++ uint64_t val, val2, usr_buf_size = usr_buf_bytes / 32; ++ int rubs_lbn, rubs_width, roec_lbn; ++ ++ EFHW_BUILD_ASSERT(RX_CFG_REG_OFST == RX_CFG_REG_KER_OFST); ++ ++ switch (nic->devtype.variant) { ++ default: ++ EFHW_ASSERT(0); ++ /* Fall-through to avoid compiler warnings. */ ++ case 'A': ++ rubs_lbn = RX_USR_BUF_SIZE_A1_LBN; ++ rubs_width = RX_USR_BUF_SIZE_A1_WIDTH; ++ roec_lbn = RX_OWNERR_CTL_A1_LBN; ++ break; ++ case 'B': ++ rubs_lbn = RX_USR_BUF_SIZE_B0_LBN; ++ rubs_width = RX_USR_BUF_SIZE_B0_WIDTH; ++ roec_lbn = RX_OWNERR_CTL_B0_LBN; ++ break; ++ } ++ ++ __DWCHCK(rubs_lbn, rubs_width); ++ __QWCHCK(roec_lbn, 1); ++ __RANGECHCK(usr_buf_size, rubs_width); ++ ++ /* Falcon requires 128 bit atomic access for this register */ ++ FALCON_LOCK_LOCK(nic); ++ falcon_read_qq(efhw_kva + RX_CFG_REG_OFST, &val, &val2); ++ ++ val &= ~((__FALCON_MASK64(rubs_width)) << rubs_lbn); ++ val |= (usr_buf_size << rubs_lbn); ++ ++ /* shouldn't be needed for a production driver */ ++ val |= ((uint64_t) 1 << roec_lbn); ++ ++ falcon_write_qq(efhw_kva + RX_CFG_REG_OFST, val, val2); ++ mmiowb(); ++ FALCON_LOCK_UNLOCK(nic); ++} ++EXPORT_SYMBOL(falcon_nic_set_rx_usr_buf_size); ++ ++ ++/*-------------------------------------------------------------------- ++ * ++ * TXDP - low level interface ++ * ++ *--------------------------------------------------------------------*/ ++ ++_DEBUG_SYM_ void falcon_nic_tx_cfg(struct efhw_nic *nic, int unlocked) ++{ ++ FALCON_LOCK_DECL; ++ volatile char __iomem *efhw_kva = EFHW_KVA(nic); ++ uint64_t val1, val2; ++ ++ EFHW_BUILD_ASSERT(TX_CFG_REG_OFST == TX_CFG_REG_KER_OFST); ++ __DWCHCK(TX_OWNERR_CTL_LBN, TX_OWNERR_CTL_WIDTH); ++ __DWCHCK(TX_NON_IP_DROP_DIS_LBN, TX_NON_IP_DROP_DIS_WIDTH); ++ ++ FALCON_LOCK_LOCK(nic); ++ falcon_read_qq(efhw_kva + TX_CFG_REG_OFST, &val1, &val2); ++ ++ /* Will flag fatal interrupts on owner id errors. This should not be ++ on for production code because there is otherwise a denial of ++ serivce attack possible */ ++ val1 |= (1 << TX_OWNERR_CTL_LBN); ++ ++ /* Setup user queue TCP/UDP only packet security */ ++ if (unlocked) ++ val1 |= (1 << TX_NON_IP_DROP_DIS_LBN); ++ else ++ val1 &= ~(1 << TX_NON_IP_DROP_DIS_LBN); ++ ++ falcon_write_qq(efhw_kva + TX_CFG_REG_OFST, val1, val2); ++ mmiowb(); ++ FALCON_LOCK_UNLOCK(nic); ++} ++ ++/*-------------------------------------------------------------------- ++ * ++ * Random thresholds - Low level interface (Would like these to be op ++ * defaults wherever possible) ++ * ++ *--------------------------------------------------------------------*/ ++ ++void falcon_nic_pace_cfg(struct efhw_nic *nic, int fb_base, int bin_thresh) ++{ ++ FALCON_LOCK_DECL; ++ volatile char __iomem *efhw_kva = EFHW_KVA(nic); ++ unsigned offset = 0; ++ uint64_t val; ++ ++ __DWCHCK(TX_PACE_FB_BASE_LBN, TX_PACE_FB_BASE_WIDTH); ++ __DWCHCK(TX_PACE_BIN_TH_LBN, TX_PACE_BIN_TH_WIDTH); ++ ++ switch (nic->devtype.variant) { ++ case 'A': offset = TX_PACE_REG_A1_OFST; break; ++ case 'B': offset = TX_PACE_REG_B0_OFST; break; ++ default: EFHW_ASSERT(0); break; ++ } ++ ++ val = (0x15 << TX_PACE_SB_NOTAF_LBN); ++ val |= (0xb << TX_PACE_SB_AF_LBN); ++ ++ val |= ((fb_base & __FALCON_MASK64(TX_PACE_FB_BASE_WIDTH)) << ++ TX_PACE_FB_BASE_LBN); ++ val |= ((bin_thresh & __FALCON_MASK64(TX_PACE_BIN_TH_WIDTH)) << ++ TX_PACE_BIN_TH_LBN); ++ ++ /* Falcon requires 128 bit atomic access for this register */ ++ FALCON_LOCK_LOCK(nic); ++ falcon_write_qq(efhw_kva + offset, val, 0); ++ mmiowb(); ++ FALCON_LOCK_UNLOCK(nic); ++} ++ ++ ++/********************************************************************** ++ * Implementation of the HAL. ******************************************** ++ **********************************************************************/ ++ ++/*---------------------------------------------------------------------------- ++ * ++ * Initialisation and configuration discovery ++ * ++ *---------------------------------------------------------------------------*/ ++ ++static int falcon_nic_init_irq_channel(struct efhw_nic *nic, int enable) ++{ ++ /* create a buffer for the irq channel */ ++ int rc; ++ ++ if (enable) { ++ rc = efhw_iopage_alloc(nic, &nic->irq_iobuff); ++ if (rc < 0) ++ return rc; ++ ++ falcon_nic_irq_addr_set(nic, ++ efhw_iopage_dma_addr(&nic->irq_iobuff)); ++ } else { ++ if (efhw_iopage_is_valid(&nic->irq_iobuff)) ++ efhw_iopage_free(nic, &nic->irq_iobuff); ++ ++ efhw_iopage_mark_invalid(&nic->irq_iobuff); ++ falcon_nic_irq_addr_set(nic, 0); ++ } ++ ++ EFHW_TRACE("%s: %lx %sable", __func__, ++ (unsigned long) efhw_iopage_dma_addr(&nic->irq_iobuff), ++ enable ? "en" : "dis"); ++ ++ return 0; ++} ++ ++static void falcon_nic_close_hardware(struct efhw_nic *nic) ++{ ++ /* check we are in possession of some hardware */ ++ if (!efhw_nic_have_hw(nic)) ++ return; ++ ++ falcon_nic_init_irq_channel(nic, 0); ++ falcon_nic_filter_dtor(nic); ++ ++ EFHW_NOTICE("%s:", __func__); ++} ++ ++static int ++falcon_nic_init_hardware(struct efhw_nic *nic, ++ struct efhw_ev_handler *ev_handlers, ++ const uint8_t *mac_addr, int non_irq_evq) ++{ ++ int rc; ++ ++ /* header sanity checks */ ++ FALCON_ASSERT_VALID(); ++ ++ /* Initialise supporting modules */ ++ rc = falcon_nic_filter_ctor(nic); ++ if (rc < 0) ++ return rc; ++ ++#if FALCON_USE_SHADOW_BUFFER_TABLE ++ CI_ZERO_ARRAY(_falcon_buffer_table, FALCON_BUFFER_TBL_NUM); ++#endif ++ ++ /* Initialise the top level hardware blocks */ ++ memcpy(nic->mac_addr, mac_addr, ETH_ALEN); ++ ++ EFHW_TRACE("%s:", __func__); ++ ++ /* nic.c:efhw_nic_init marks all the interrupt units as unused. ++ ++ ?? TODO we should be able to request the non-interrupting event ++ queue and the net driver's (for a net driver that is using libefhw) ++ additional RSS queues here. ++ ++ Result would be that that net driver could call ++ nic.c:efhw_nic_allocate_common_hardware_resources() and that the ++ IFDEF FALCON's can be removed from ++ nic.c:efhw_nic_allocate_common_hardware_resources() ++ */ ++ nic->irq_unit = INT_EN_REG_CHAR_OFST; ++ ++ /***************************************************************** ++ * The rest of this function deals with initialization of the NICs ++ * hardware (as opposed to the initialization of the ++ * struct efhw_nic data structure */ ++ ++ /* char driver grabs SRM events onto the non interrupting ++ * event queue */ ++ falcon_nic_srm_upd_evq(nic, non_irq_evq); ++ ++ /* RXDP tweaks */ ++ ++ /* ?? bug2396 rx_cfg should be ok so long as the net driver ++ * always pushes buffers big enough for the link MTU */ ++ ++ /* set the RX buffer cutoff size to be the same as PAGE_SIZE. ++ * Use this value when we think that there will be a lot of ++ * jumbo frames. ++ * ++ * The default value 1600 is useful when packets are small, ++ * but would means that jumbo frame RX queues would need more ++ * descriptors pushing */ ++ falcon_nic_set_rx_usr_buf_size(nic, FALCON_RX_USR_BUF_SIZE); ++ ++ /* TXDP tweaks */ ++ /* ?? bug2396 looks ok */ ++ falcon_nic_tx_cfg(nic, /*unlocked(for non-UDP/TCP)= */ 0); ++ falcon_nic_pace_cfg(nic, 4, 2); ++ ++ /* ?? bug2396 ++ * netdriver must load first or else must RMW this register */ ++ falcon_nic_rx_filter_ctl_set(nic, RX_FILTER_CTL_SRCH_LIMIT_TCP_FULL, ++ RX_FILTER_CTL_SRCH_LIMIT_TCP_WILD, ++ RX_FILTER_CTL_SRCH_LIMIT_UDP_FULL, ++ RX_FILTER_CTL_SRCH_LIMIT_UDP_WILD); ++ ++ if (!(nic->flags & NIC_FLAG_NO_INTERRUPT)) { ++ rc = efhw_keventq_ctor(nic, FALCON_EVQ_CHAR, ++ &nic->interrupting_evq, ev_handlers); ++ if (rc < 0) { ++ EFHW_ERR("%s: efhw_keventq_ctor() failed (%d) evq=%d", ++ __func__, rc, FALCON_EVQ_CHAR); ++ return rc; ++ } ++ } ++ rc = efhw_keventq_ctor(nic, non_irq_evq, ++ &nic->non_interrupting_evq, NULL); ++ if (rc < 0) { ++ EFHW_ERR("%s: efhw_keventq_ctor() failed (%d) evq=%d", ++ __func__, rc, non_irq_evq); ++ return rc; ++ } ++ ++ /* allocate IRQ channel */ ++ rc = falcon_nic_init_irq_channel(nic, 1); ++ /* ignore failure at user-level for eftest */ ++ if ((rc < 0) && !(nic->options & NIC_OPT_EFTEST)) ++ return rc; ++ ++ return 0; ++} ++ ++/*-------------------------------------------------------------------- ++ * ++ * Interrupt ++ * ++ *--------------------------------------------------------------------*/ ++ ++static void ++falcon_nic_interrupt_enable(struct efhw_nic *nic) ++{ ++ struct efhw_keventq *q; ++ unsigned rdptr; ++ ++ if (nic->flags & NIC_FLAG_NO_INTERRUPT) ++ return; ++ ++ /* Enable driver interrupts */ ++ EFHW_NOTICE("%s: enable master interrupt", __func__); ++ falcon_nic_interrupt_hw_enable(nic); ++ ++ /* An interrupting eventq must start of day ack its read pointer */ ++ q = &nic->interrupting_evq; ++ rdptr = EFHW_EVENT_OFFSET(q, q, 1) / sizeof(efhw_event_t); ++ falcon_nic_evq_ack(nic, FALCON_EVQ_CHAR, rdptr, false); ++ EFHW_NOTICE("%s: ACK evq[%d]:%x", __func__, ++ FALCON_EVQ_CHAR, rdptr); ++} ++ ++static void falcon_nic_interrupt_disable(struct efhw_nic *nic) ++{ ++ /* NB. No need to check for NIC_FLAG_NO_INTERRUPT, as ++ ** falcon_nic_interrupt_hw_disable() will do it. */ ++ falcon_nic_interrupt_hw_disable(nic); ++} ++ ++static void ++falcon_nic_set_interrupt_moderation(struct efhw_nic *nic, int evq, ++ uint32_t val) ++{ ++ if (evq < 0) ++ evq = FALCON_EVQ_CHAR; ++ ++ falcon_ab_timer_tbl_set(nic, evq, TIMER_MODE_INT_HLDOFF, val / 5); ++} ++ ++static inline void legacy_irq_ack(struct efhw_nic *nic) ++{ ++ EFHW_ASSERT(!(nic->flags & NIC_FLAG_NO_INTERRUPT)); ++ ++ if (!(nic->flags & NIC_FLAG_MSI)) { ++ writel(1, EFHW_KVA(nic) + INT_ACK_REG_CHAR_A1_OFST); ++ mmiowb(); ++ /* ?? FIXME: We should be doing a read here to ensure IRQ is ++ * thoroughly acked before we return from ISR. */ ++ } ++} ++ ++static int falcon_nic_interrupt(struct efhw_nic *nic) ++{ ++ uint32_t *syserr_ptr = ++ (uint32_t *) efhw_iopage_ptr(&nic->irq_iobuff); ++ int handled = 0; ++ int done_ack = 0; ++ ++ EFHW_ASSERT(!(nic->flags & NIC_FLAG_NO_INTERRUPT)); ++ EFHW_ASSERT(syserr_ptr); ++ ++ /* FIFO fill level interrupt - just log it. */ ++ if (unlikely(*(syserr_ptr + (DW0_OFST / 4)))) { ++ EFHW_WARN("%s: *** FIFO *** %x", __func__, ++ *(syserr_ptr + (DW0_OFST / 4))); ++ *(syserr_ptr + (DW0_OFST / 4)) = 0; ++ handled++; ++ } ++ ++ /* Fatal interrupts. */ ++ if (unlikely(*(syserr_ptr + (DW2_OFST / 4)))) { ++ *(syserr_ptr + (DW2_OFST / 4)) = 0; ++ falcon_nic_handle_fatal_int(nic); ++ handled++; ++ } ++ ++ /* Event queue interrupt. For legacy interrupts we have to check ++ * that the interrupt is for us, because it could be shared. */ ++ if (*(syserr_ptr + (DW1_OFST / 4))) { ++ *(syserr_ptr + (DW1_OFST / 4)) = 0; ++ /* ACK must come before callback to handler fn. */ ++ legacy_irq_ack(nic); ++ done_ack = 1; ++ handled++; ++ if (nic->irq_handler) ++ nic->irq_handler(nic, 0); ++ } ++ ++ if (unlikely(!done_ack)) { ++ if (!handled) ++ /* Shared interrupt line (hopefully). */ ++ return 0; ++ legacy_irq_ack(nic); ++ } ++ ++ EFHW_TRACE("%s: handled %d", __func__, handled); ++ return 1; ++} ++ ++/*-------------------------------------------------------------------- ++ * ++ * Event Management - and SW event posting ++ * ++ *--------------------------------------------------------------------*/ ++ ++static void ++falcon_nic_event_queue_enable(struct efhw_nic *nic, uint evq, uint evq_size, ++ dma_addr_t q_base_addr, /* not used */ ++ uint buf_base_id, int interrupting) ++{ ++ EFHW_ASSERT(nic); ++ ++ /* Whether or not queue has an interrupt depends on ++ * instance number and h/w variant, so [interrupting] is ++ * ignored. ++ */ ++ falcon_ab_timer_tbl_set(nic, evq, 0/*disable*/, 0); ++ ++ falcon_nic_evq_ptr_tbl(nic, evq, 1, buf_base_id, evq_size); ++ EFHW_TRACE("%s: enable evq %u size %u", __func__, evq, evq_size); ++} ++ ++static void ++falcon_nic_event_queue_disable(struct efhw_nic *nic, uint evq, int timer_only) ++{ ++ EFHW_ASSERT(nic); ++ ++ falcon_ab_timer_tbl_set(nic, evq, 0 /* disable */ , 0); ++ ++ if (!timer_only) ++ falcon_nic_evq_ptr_tbl(nic, evq, 0, 0, 0); ++ EFHW_TRACE("%s: disenable evq %u", __func__, evq); ++} ++ ++static void ++falcon_nic_wakeup_request(struct efhw_nic *nic, dma_addr_t q_base_addr, ++ int next_i, int evq) ++{ ++ EFHW_ASSERT(evq > FALCON_EVQ_CHAR); ++ falcon_nic_evq_ack(nic, evq, next_i, true); ++ EFHW_TRACE("%s: evq %d next_i %d", __func__, evq, next_i); ++} ++ ++static void falcon_nic_sw_event(struct efhw_nic *nic, int data, int evq) ++{ ++ uint64_t ev_data = data; ++ ++ ev_data &= ~FALCON_EVENT_CODE_MASK; ++ ev_data |= FALCON_EVENT_CODE_SW; ++ ++ falcon_drv_ev(nic, ev_data, evq); ++ EFHW_NOTICE("%s: evq[%d]->%x", __func__, evq, data); ++} ++ ++ ++/*-------------------------------------------------------------------- ++ * ++ * Buffer table - helpers ++ * ++ *--------------------------------------------------------------------*/ ++ ++#define FALCON_LAZY_COMMIT_HWM (FALCON_BUFFER_UPD_MAX - 16) ++ ++/* Note re.: ++ * falcon_nic_buffer_table_lazy_commit(struct efhw_nic *nic) ++ * falcon_nic_buffer_table_update_poll(struct efhw_nic *nic) ++ * falcon_nic_buffer_table_confirm(struct efhw_nic *nic) ++ * -- these are no-ops in the user-level driver because it would need to ++ * coordinate with the real driver on the number of outstanding commits. ++ * ++ * An exception is made for eftest apps, which manage the hardware without ++ * using the char driver. ++ */ ++ ++static inline void falcon_nic_buffer_table_lazy_commit(struct efhw_nic *nic) ++{ ++ /* Do nothing if operating in synchronous mode. */ ++ if (!nic->irq_handler) ++ return; ++} ++ ++static inline void falcon_nic_buffer_table_update_poll(struct efhw_nic *nic) ++{ ++ FALCON_LOCK_DECL; ++ int count = 0, rc = 0; ++ ++ /* We can be called here early days */ ++ if (!nic->irq_handler) ++ return; ++ ++ /* If we need to gather buffer update events then poll the ++ non-interrupting event queue */ ++ ++ /* For each _buffer_table_commit there will be an update done ++ event. We don't keep track of how many buffers each commit has ++ committed, just make sure that all the expected events have been ++ gathered */ ++ FALCON_LOCK_LOCK(nic); ++ ++ EFHW_TRACE("%s: %d", __func__, nic->buf_commit_outstanding); ++ ++ while (nic->buf_commit_outstanding > 0) { ++ /* we're not expecting to handle any events that require ++ * upcalls into the core driver */ ++ struct efhw_ev_handler handler; ++ memset(&handler, 0, sizeof(handler)); ++ nic->non_interrupting_evq.ev_handlers = &handler; ++ rc = efhw_keventq_poll(nic, &nic->non_interrupting_evq); ++ nic->non_interrupting_evq.ev_handlers = NULL; ++ ++ if (rc < 0) { ++ EFHW_ERR("%s: poll ERROR (%d:%d) ***** ", ++ __func__, rc, ++ nic->buf_commit_outstanding); ++ goto out; ++ } ++ ++ FALCON_LOCK_UNLOCK(nic); ++ ++ if (count++) ++ udelay(1); ++ ++ if (count > 1000) { ++ EFHW_WARN("%s: poll Timeout ***** (%d)", __func__, ++ nic->buf_commit_outstanding); ++ nic->buf_commit_outstanding = 0; ++ return; ++ } ++ FALCON_LOCK_LOCK(nic); ++ } ++ ++out: ++ FALCON_LOCK_UNLOCK(nic); ++ return; ++} ++ ++void falcon_nic_buffer_table_confirm(struct efhw_nic *nic) ++{ ++ /* confirm buffer table updates - should be used for items where ++ loss of data would be unacceptable. E.g for the buffers that back ++ an event or DMA queue */ ++ FALCON_LOCK_DECL; ++ ++ /* Do nothing if operating in synchronous mode. */ ++ if (!nic->irq_handler) ++ return; ++ ++ FALCON_LOCK_LOCK(nic); ++ ++ _falcon_nic_buffer_table_commit(nic); ++ ++ FALCON_LOCK_UNLOCK(nic); ++ ++ falcon_nic_buffer_table_update_poll(nic); ++} ++ ++/*-------------------------------------------------------------------- ++ * ++ * Buffer table - API ++ * ++ *--------------------------------------------------------------------*/ ++ ++static void ++falcon_nic_buffer_table_clear(struct efhw_nic *nic, int buffer_id, int num) ++{ ++ FALCON_LOCK_DECL; ++ FALCON_LOCK_LOCK(nic); ++ _falcon_nic_buffer_table_clear(nic, buffer_id, num); ++ FALCON_LOCK_UNLOCK(nic); ++} ++ ++static void ++falcon_nic_buffer_table_set(struct efhw_nic *nic, dma_addr_t dma_addr, ++ uint bufsz, uint region, ++ int own_id, int buffer_id) ++{ ++ FALCON_LOCK_DECL; ++ ++ EFHW_ASSERT(region < FALCON_REGION_NUM); ++ ++ EFHW_ASSERT((bufsz == EFHW_4K) || ++ (bufsz == EFHW_8K && FALCON_BUFFER_TABLE_FULL_MODE)); ++ ++ falcon_nic_buffer_table_update_poll(nic); ++ ++ FALCON_LOCK_LOCK(nic); ++ ++ _falcon_nic_buffer_table_set(nic, dma_addr, bufsz, region, own_id, ++ buffer_id); ++ ++ falcon_nic_buffer_table_lazy_commit(nic); ++ ++ FALCON_LOCK_UNLOCK(nic); ++} ++ ++void ++falcon_nic_buffer_table_set_n(struct efhw_nic *nic, int buffer_id, ++ dma_addr_t dma_addr, uint bufsz, uint region, ++ int n_pages, int own_id) ++{ ++ /* used to set up a contiguous range of buffers */ ++ FALCON_LOCK_DECL; ++ ++ EFHW_ASSERT(region < FALCON_REGION_NUM); ++ ++ EFHW_ASSERT((bufsz == EFHW_4K) || ++ (bufsz == EFHW_8K && FALCON_BUFFER_TABLE_FULL_MODE)); ++ ++ while (n_pages--) { ++ ++ falcon_nic_buffer_table_update_poll(nic); ++ ++ FALCON_LOCK_LOCK(nic); ++ ++ _falcon_nic_buffer_table_set(nic, dma_addr, bufsz, region, ++ own_id, buffer_id++); ++ ++ falcon_nic_buffer_table_lazy_commit(nic); ++ ++ FALCON_LOCK_UNLOCK(nic); ++ ++ dma_addr += bufsz; ++ } ++} ++ ++/*-------------------------------------------------------------------- ++ * ++ * DMA Queues - mid level API ++ * ++ *--------------------------------------------------------------------*/ ++ ++#if BUG5302_WORKAROUND ++ ++/* Tx queues can get stuck if the software write pointer is set to an index ++ * beyond the configured size of the queue, such that they will not flush. ++ * This code can be run before attempting a flush; it will detect the bogus ++ * value and reset it. This fixes most instances of this problem, although ++ * sometimes it does not work, or we may not detect it in the first place, ++ * if the out-of-range value was replaced by an in-range value earlier. ++ * (In those cases we have to apply a bigger hammer later, if we see that ++ * the queue is still not flushing.) ++ */ ++static void ++falcon_check_for_bogus_tx_dma_wptr(struct efhw_nic *nic, uint dmaq) ++{ ++ FALCON_LOCK_DECL; ++ uint64_t val_low64, val_high64; ++ uint64_t size, hwptr, swptr, val; ++ volatile char __iomem *efhw_kva = EFHW_KVA(nic); ++ ulong offset = falcon_dma_tx_q_offset(nic, dmaq); ++ ++ /* Falcon requires 128 bit atomic access for this register */ ++ FALCON_LOCK_LOCK(nic); ++ falcon_read_qq(efhw_kva + offset, &val_low64, &val_high64); ++ FALCON_LOCK_UNLOCK(nic); ++ ++ size = (val_low64 >> TX_DESCQ_SIZE_LBN) ++ & __FALCON_MASK64(TX_DESCQ_SIZE_WIDTH); ++ size = (1 << size) * 512; ++ hwptr = (val_high64 >> __DW3(TX_DESCQ_HW_RPTR_LBN)) ++ & __FALCON_MASK64(TX_DESCQ_HW_RPTR_WIDTH); ++ swptr = (val_low64 >> TX_DESCQ_SW_WPTR_LBN) ++ & __FALCON_MASK64(__LW2(TX_DESCQ_SW_WPTR_LBN)); ++ val = (val_high64) ++ & ++ __FALCON_MASK64(__DW3 ++ (TX_DESCQ_SW_WPTR_LBN + TX_DESCQ_SW_WPTR_WIDTH)); ++ val = val << __LW2(TX_DESCQ_SW_WPTR_LBN); ++ swptr = swptr | val; ++ ++ if (swptr >= size) { ++ EFHW_WARN("Resetting bad write pointer for TXQ[%d]", dmaq); ++ writel((uint32_t) ((hwptr + 0) & (size - 1)), ++ efhw_kva + falcon_tx_dma_page_addr(dmaq) + 12); ++ mmiowb(); ++ } ++} ++ ++/* Here's that "bigger hammer": we reset all the pointers (hardware read, ++ * hardware descriptor cache read, software write) to zero. ++ */ ++void falcon_clobber_tx_dma_ptrs(struct efhw_nic *nic, uint dmaq) ++{ ++ FALCON_LOCK_DECL; ++ uint64_t val_low64, val_high64; ++ volatile char __iomem *efhw_kva = EFHW_KVA(nic); ++ ulong offset = falcon_dma_tx_q_offset(nic, dmaq); ++ ++ EFHW_WARN("Recovering stuck TXQ[%d]", dmaq); ++ FALCON_LOCK_LOCK(nic); ++ falcon_read_qq(efhw_kva + offset, &val_low64, &val_high64); ++ val_high64 &= ~(__FALCON_MASK64(TX_DESCQ_HW_RPTR_WIDTH) ++ << __DW3(TX_DESCQ_HW_RPTR_LBN)); ++ val_high64 &= ~(__FALCON_MASK64(TX_DC_HW_RPTR_WIDTH) ++ << __DW3(TX_DC_HW_RPTR_LBN)); ++ falcon_write_qq(efhw_kva + offset, val_low64, val_high64); ++ mmiowb(); ++ writel(0, efhw_kva + falcon_tx_dma_page_addr(dmaq) + 12); ++ mmiowb(); ++ FALCON_LOCK_UNLOCK(nic); ++} ++ ++#endif ++ ++static inline int ++__falcon_really_flush_tx_dma_channel(struct efhw_nic *nic, uint dmaq) ++{ ++ FALCON_LOCK_DECL; ++ volatile char __iomem *efhw_kva = EFHW_KVA(nic); ++ uint val; ++ ++ EFHW_BUILD_ASSERT(TX_FLUSH_DESCQ_REG_KER_OFST == ++ TX_FLUSH_DESCQ_REG_OFST); ++ ++ __DWCHCK(TX_FLUSH_DESCQ_CMD_LBN, TX_FLUSH_DESCQ_CMD_WIDTH); ++ __DWCHCK(TX_FLUSH_DESCQ_LBN, TX_FLUSH_DESCQ_WIDTH); ++ __RANGECHCK(dmaq, TX_FLUSH_DESCQ_WIDTH); ++ ++ val = ((1 << TX_FLUSH_DESCQ_CMD_LBN) | (dmaq << TX_FLUSH_DESCQ_LBN)); ++ ++ EFHW_TRACE("TX DMA flush[%d]", dmaq); ++ ++#if BUG5302_WORKAROUND ++ falcon_check_for_bogus_tx_dma_wptr(nic, dmaq); ++#endif ++ ++ /* Falcon requires 128 bit atomic access for this register */ ++ FALCON_LOCK_LOCK(nic); ++ falcon_write_qq(efhw_kva + TX_FLUSH_DESCQ_REG_OFST, ++ val, FALCON_ATOMIC_TX_FLUSH_DESCQ); ++ ++ mmiowb(); ++ FALCON_LOCK_UNLOCK(nic); ++ return 0; ++} ++ ++static inline int ++__falcon_is_tx_dma_channel_flushed(struct efhw_nic *nic, uint dmaq) ++{ ++ FALCON_LOCK_DECL; ++ uint64_t val_low64, val_high64; ++ uint64_t enable, flush_pending; ++ volatile char __iomem *efhw_kva = EFHW_KVA(nic); ++ ulong offset = falcon_dma_tx_q_offset(nic, dmaq); ++ ++ /* Falcon requires 128 bit atomic access for this register */ ++ FALCON_LOCK_LOCK(nic); ++ falcon_read_qq(efhw_kva + offset, &val_low64, &val_high64); ++ FALCON_LOCK_UNLOCK(nic); ++ ++ /* should see one of three values for these 2 bits ++ * 1, queue enabled no flush pending ++ * - i.e. first flush request ++ * 2, queue enabled, flush pending ++ * - i.e. request to reflush before flush finished ++ * 3, queue disabled (no flush pending) ++ * - flush complete ++ */ ++ __DWCHCK(TX_DESCQ_FLUSH_LBN, TX_DESCQ_FLUSH_WIDTH); ++ __DW3CHCK(TX_DESCQ_EN_LBN, TX_DESCQ_EN_WIDTH); ++ enable = val_high64 & (1 << __DW3(TX_DESCQ_EN_LBN)); ++ flush_pending = val_low64 & (1 << TX_DESCQ_FLUSH_LBN); ++ ++ if (enable && !flush_pending) ++ return 0; ++ ++ EFHW_TRACE("%d, %s: %s, %sflush pending", dmaq, __func__, ++ enable ? "enabled" : "disabled", ++ flush_pending ? "" : "NO "); ++ /* still in progress */ ++ if (enable && flush_pending) ++ return -EALREADY; ++ ++ return -EAGAIN; ++} ++ ++static int falcon_flush_tx_dma_channel(struct efhw_nic *nic, uint dmaq) ++{ ++ int rc; ++ rc = __falcon_is_tx_dma_channel_flushed(nic, dmaq); ++ if (rc < 0) { ++ EFHW_WARN("%s: failed %d", __func__, rc); ++ return rc; ++ } ++ return __falcon_really_flush_tx_dma_channel(nic, dmaq); ++} ++ ++static int ++__falcon_really_flush_rx_dma_channel(struct efhw_nic *nic, uint dmaq) ++{ ++ FALCON_LOCK_DECL; ++ volatile char __iomem *efhw_kva = EFHW_KVA(nic); ++ uint val; ++ ++ EFHW_BUILD_ASSERT(RX_FLUSH_DESCQ_REG_KER_OFST == ++ RX_FLUSH_DESCQ_REG_OFST); ++ ++ __DWCHCK(RX_FLUSH_DESCQ_CMD_LBN, RX_FLUSH_DESCQ_CMD_WIDTH); ++ __DWCHCK(RX_FLUSH_DESCQ_LBN, RX_FLUSH_DESCQ_WIDTH); ++ __RANGECHCK(dmaq, RX_FLUSH_DESCQ_WIDTH); ++ ++ val = ((1 << RX_FLUSH_DESCQ_CMD_LBN) | (dmaq << RX_FLUSH_DESCQ_LBN)); ++ ++ EFHW_TRACE("RX DMA flush[%d]", dmaq); ++ ++ /* Falcon requires 128 bit atomic access for this register */ ++ FALCON_LOCK_LOCK(nic); ++ falcon_write_qq(efhw_kva + RX_FLUSH_DESCQ_REG_OFST, val, ++ FALCON_ATOMIC_RX_FLUSH_DESCQ); ++ mmiowb(); ++ FALCON_LOCK_UNLOCK(nic); ++ return 0; ++} ++ ++static inline int ++__falcon_is_rx_dma_channel_flushed(struct efhw_nic *nic, uint dmaq) ++{ ++ FALCON_LOCK_DECL; ++ uint64_t val; ++ volatile char __iomem *efhw_kva = EFHW_KVA(nic); ++ ulong offset = falcon_dma_rx_q_offset(nic, dmaq); ++ ++ /* Falcon requires 128 bit atomic access for this register */ ++ FALCON_LOCK_LOCK(nic); ++ falcon_read_q(efhw_kva + offset, &val); ++ FALCON_LOCK_UNLOCK(nic); ++ ++ __DWCHCK(RX_DESCQ_EN_LBN, RX_DESCQ_EN_WIDTH); ++ ++ /* is it enabled? */ ++ return (val & (1 << RX_DESCQ_EN_LBN)) ++ ? 0 : -EAGAIN; ++} ++ ++static int falcon_flush_rx_dma_channel(struct efhw_nic *nic, uint dmaq) ++{ ++ int rc; ++ rc = __falcon_is_rx_dma_channel_flushed(nic, dmaq); ++ if (rc < 0) { ++ EFHW_ERR("%s: failed %d", __func__, rc); ++ return rc; ++ } ++ return __falcon_really_flush_rx_dma_channel(nic, dmaq); ++} ++ ++/*-------------------------------------------------------------------- ++ * ++ * Falcon specific event callbacks ++ * ++ *--------------------------------------------------------------------*/ ++ ++int ++falcon_handle_char_event(struct efhw_nic *nic, struct efhw_ev_handler *h, ++ efhw_event_t *ev) ++{ ++ EFHW_TRACE("DRIVER EVENT: "FALCON_EVENT_FMT, ++ FALCON_EVENT_PRI_ARG(*ev)); ++ ++ switch (FALCON_EVENT_DRIVER_SUBCODE(ev)) { ++ ++ case TX_DESCQ_FLS_DONE_EV_DECODE: ++ EFHW_TRACE("TX[%d] flushed", ++ (int)FALCON_EVENT_TX_FLUSH_Q_ID(ev)); ++ efhw_handle_txdmaq_flushed(nic, h, ev); ++ break; ++ ++ case RX_DESCQ_FLS_DONE_EV_DECODE: ++ EFHW_TRACE("RX[%d] flushed", ++ (int)FALCON_EVENT_TX_FLUSH_Q_ID(ev)); ++ efhw_handle_rxdmaq_flushed(nic, h, ev); ++ break; ++ ++ case SRM_UPD_DONE_EV_DECODE: ++ nic->buf_commit_outstanding = ++ max(0, nic->buf_commit_outstanding - 1); ++ EFHW_TRACE("COMMIT DONE %d", nic->buf_commit_outstanding); ++ break; ++ ++ case EVQ_INIT_DONE_EV_DECODE: ++ EFHW_TRACE("%sEVQ INIT", ""); ++ break; ++ ++ case WAKE_UP_EV_DECODE: ++ EFHW_TRACE("%sWAKE UP", ""); ++ efhw_handle_wakeup_event(nic, h, ev); ++ break; ++ ++ case TIMER_EV_DECODE: ++ EFHW_TRACE("%sTIMER", ""); ++ efhw_handle_timeout_event(nic, h, ev); ++ break; ++ ++ case RX_DESCQ_FLSFF_OVFL_EV_DECODE: ++ /* This shouldn't happen. */ ++ EFHW_ERR("%s: RX flush fifo overflowed", __func__); ++ return -EINVAL; ++ ++ default: ++ EFHW_TRACE("UNKOWN DRIVER EVENT: " FALCON_EVENT_FMT, ++ FALCON_EVENT_PRI_ARG(*ev)); ++ break; ++ } ++ return 0; ++} ++ ++ ++/*-------------------------------------------------------------------- ++ * ++ * Filter search depth control ++ * ++ *--------------------------------------------------------------------*/ ++ ++ ++#define Q0_READ(q0, name) \ ++ ((unsigned)(((q0) >> name##_LBN) & (__FALCON_MASK64(name##_WIDTH)))) ++#define Q0_MASK(name) \ ++ ((__FALCON_MASK64(name##_WIDTH)) << name##_LBN) ++#define Q0_VALUE(name, value) \ ++ (((uint64_t)(value)) << name##_LBN) ++ ++#define Q1_READ(q1, name) \ ++ ((unsigned)(((q1) >> (name##_LBN - 64)) & \ ++ (__FALCON_MASK64(name##_WIDTH)))) ++#define Q1_MASK(name) \ ++ ((__FALCON_MASK64(name##_WIDTH)) << (name##_LBN - 64)) ++#define Q1_VALUE(name, value) \ ++ (((uint64_t)(value)) << (name##_LBN - 64)) ++ ++ ++void ++falcon_nic_get_rx_filter_search_limits(struct efhw_nic *nic, ++ struct efhw_filter_search_limits *lim, ++ int use_raw_values) ++{ ++ volatile char __iomem *efhw_kva = EFHW_KVA(nic); ++ FALCON_LOCK_DECL; ++ uint64_t q0, q1; ++ unsigned ff = (use_raw_values ? 0 : RX_FILTER_CTL_SRCH_FUDGE_FULL); ++ unsigned wf = (use_raw_values ? 0 : RX_FILTER_CTL_SRCH_FUDGE_WILD); ++ ++ FALCON_LOCK_LOCK(nic); ++ falcon_read_qq(efhw_kva + RX_FILTER_CTL_REG_OFST, &q0, &q1); ++ FALCON_LOCK_UNLOCK(nic); ++ ++ lim->tcp_full = Q0_READ(q0, TCP_FULL_SRCH_LIMIT) - ff; ++ lim->tcp_wild = Q0_READ(q0, TCP_WILD_SRCH_LIMIT) - wf; ++ lim->udp_full = Q0_READ(q0, UDP_FULL_SRCH_LIMIT) - ff; ++ lim->udp_wild = Q0_READ(q0, UDP_WILD_SRCH_LIMIT) - wf; ++} ++EXPORT_SYMBOL(falcon_nic_get_rx_filter_search_limits); ++ ++ ++void ++falcon_nic_set_rx_filter_search_limits(struct efhw_nic *nic, ++ struct efhw_filter_search_limits *lim, ++ int use_raw_values) ++{ ++ volatile char __iomem *efhw_kva = EFHW_KVA(nic); ++ FALCON_LOCK_DECL; ++ uint64_t q0, q1; ++ unsigned ff = (use_raw_values ? 0 : RX_FILTER_CTL_SRCH_FUDGE_FULL); ++ unsigned wf = (use_raw_values ? 0 : RX_FILTER_CTL_SRCH_FUDGE_WILD); ++ ++ FALCON_LOCK_LOCK(nic); ++ falcon_read_qq(efhw_kva + RX_FILTER_CTL_REG_OFST, &q0, &q1); ++ ++ q0 &= ~Q0_MASK(TCP_FULL_SRCH_LIMIT); ++ q0 &= ~Q0_MASK(TCP_WILD_SRCH_LIMIT); ++ q0 &= ~Q0_MASK(UDP_FULL_SRCH_LIMIT); ++ q0 &= ~Q0_MASK(UDP_WILD_SRCH_LIMIT); ++ q0 |= Q0_VALUE(TCP_FULL_SRCH_LIMIT, lim->tcp_full + ff); ++ q0 |= Q0_VALUE(TCP_WILD_SRCH_LIMIT, lim->tcp_wild + wf); ++ q0 |= Q0_VALUE(UDP_FULL_SRCH_LIMIT, lim->udp_full + ff); ++ q0 |= Q0_VALUE(UDP_WILD_SRCH_LIMIT, lim->udp_wild + wf); ++ nic->tcp_full_srch.max = lim->tcp_full + ff ++ - RX_FILTER_CTL_SRCH_FUDGE_FULL; ++ nic->tcp_wild_srch.max = lim->tcp_wild + wf ++ - RX_FILTER_CTL_SRCH_FUDGE_WILD; ++ nic->udp_full_srch.max = lim->udp_full + ff ++ - RX_FILTER_CTL_SRCH_FUDGE_FULL; ++ nic->udp_wild_srch.max = lim->udp_wild + wf ++ - RX_FILTER_CTL_SRCH_FUDGE_WILD; ++ ++ falcon_write_qq(efhw_kva + RX_FILTER_CTL_REG_OFST, q0, q1); ++ mmiowb(); ++ FALCON_LOCK_UNLOCK(nic); ++} ++EXPORT_SYMBOL(falcon_nic_set_rx_filter_search_limits); ++ ++ ++#undef READ_Q0 ++#undef Q0_MASK ++#undef Q0_VALUE ++#undef READ_Q1 ++#undef Q1_MASK ++#undef Q1_VALUE ++ ++ ++/*-------------------------------------------------------------------- ++ * ++ * New unified filter API ++ * ++ *--------------------------------------------------------------------*/ ++ ++ ++#if FALCON_FULL_FILTER_CACHE ++static inline struct efhw_filter_spec * ++filter_spec_cache_entry(struct efhw_nic *nic, int filter_idx) ++{ ++ EFHW_ASSERT(nic->filter_spec_cache); ++ return &nic->filter_spec_cache[filter_idx]; ++} ++#endif ++ ++ ++static int filter_is_active(struct efhw_nic *nic, int filter_idx) ++{ ++ return nic->filter_in_use[filter_idx]; ++} ++ ++ ++static void set_filter_cache_entry(struct efhw_nic *nic, ++ struct efhw_filter_spec *spec, ++ int filter_idx) ++{ ++ nic->filter_in_use[filter_idx] = 1; ++#if FALCON_FULL_FILTER_CACHE ++ memcpy(filter_spec_cache_entry(nic, filter_idx), spec, ++ sizeof(struct efhw_filter_spec)); ++#endif ++} ++ ++ ++static void clear_filter_cache_entry(struct efhw_nic *nic, ++ int filter_idx) ++{ ++ nic->filter_in_use[filter_idx] = 0; ++#if FALCON_FULL_FILTER_CACHE ++ memset(filter_spec_cache_entry(nic, filter_idx), 0, ++ sizeof(struct efhw_filter_spec)); ++#endif ++} ++ ++ ++#if FALCON_FULL_FILTER_CACHE ++static int filter_is_duplicate(struct efhw_nic *nic, ++ struct efhw_filter_spec *spec, int filter_idx) ++{ ++ struct efhw_filter_spec *cmp; ++ ++ cmp = filter_spec_cache_entry(nic, filter_idx); ++ ++ EFHW_ASSERT(filter_is_active(nic, filter_idx)); ++ ++ return (spec->saddr_le32 == cmp->saddr_le32) && ++ (spec->daddr_le32 == cmp->daddr_le32) && ++ (spec->sport_le16 == cmp->sport_le16) && ++ (spec->dport_le16 == cmp->dport_le16) && ++ (spec->tcp == cmp->tcp) && ++ (spec->full == cmp->full); ++} ++#endif ++ ++ ++static void common_build_ip_filter(struct efhw_nic *nic, int tcp, int full, ++ int rss, int scatter, uint dmaq_id, ++ unsigned saddr_le32, unsigned sport_le16, ++ unsigned daddr_le32, unsigned dport_le16, ++ uint64_t *q0, uint64_t *q1) ++{ ++ uint64_t v1, v2, v3, v4; ++ unsigned tmp_port_le16; ++ ++ if (!full) { ++ saddr_le32 = 0; ++ sport_le16 = 0; ++ if (!tcp) { ++ tmp_port_le16 = sport_le16; ++ sport_le16 = dport_le16; ++ dport_le16 = tmp_port_le16; ++ } ++ } ++ ++ v4 = (((!tcp) << __DW4(TCP_UDP_0_LBN)) | ++ (dmaq_id << __DW4(RXQ_ID_0_LBN))); ++ ++ switch (nic->devtype.variant) { ++ case 'A': ++ EFHW_ASSERT(!rss); ++ break; ++ case 'B': ++ v4 |= scatter << __DW4(SCATTER_EN_0_B0_LBN); ++ v4 |= rss << __DW4(RSS_EN_0_B0_LBN); ++ break; ++ default: ++ EFHW_ASSERT(0); ++ break; ++ } ++ ++ v3 = daddr_le32; ++ v2 = ((dport_le16 << __DW2(DEST_PORT_TCP_0_LBN)) | ++ (__HIGH(saddr_le32, SRC_IP_0_LBN, SRC_IP_0_WIDTH))); ++ v1 = ((__LOW(saddr_le32, SRC_IP_0_LBN, SRC_IP_0_WIDTH)) | ++ (sport_le16 << SRC_TCP_DEST_UDP_0_LBN)); ++ ++ *q0 = (v2 << 32) | v1; ++ *q1 = (v4 << 32) | v3; ++} ++ ++ ++static void build_filter(struct efhw_nic *nic, struct efhw_filter_spec *spec, ++ unsigned *key, unsigned *tbl_size, ++ struct efhw_filter_depth **depth, ++ uint64_t *q0, uint64_t *q1) ++{ ++ *key = falcon_hash_get_ip_key(spec->saddr_le32, ++ spec->sport_le16, ++ spec->daddr_le32, ++ spec->dport_le16, ++ spec->tcp, ++ spec->full); ++ *tbl_size = nic->ip_filter_tbl_size; ++ if (spec->tcp && spec->full) ++ *depth = &nic->tcp_full_srch; ++ else if (spec->tcp && !spec->full) ++ *depth = &nic->tcp_wild_srch; ++ else if (!spec->tcp && spec->full) ++ *depth = &nic->udp_full_srch; ++ else ++ *depth = &nic->udp_wild_srch; ++ common_build_ip_filter(nic, spec->tcp, spec->full, ++ spec->rss, spec->scatter, ++ spec->dmaq_id, ++ spec->saddr_le32, ++ spec->sport_le16, ++ spec->daddr_le32, ++ spec->dport_le16, ++ q0, q1); ++} ++ ++ ++#if FALCON_VERIFY_FILTERS ++static void verify_filters(struct efhw_nic *nic) ++{ ++ unsigned table_offset, table_stride; ++ unsigned i, dummy_key, dummy_tbl_size; ++ struct efhw_filter_depth *dummy_depth; ++ unsigned filter_tbl_size; ++ struct efhw_filter_spec *spec; ++ uint64_t q0_expect, q1_expect, q0_got, q1_got; ++ ++ filter_tbl_size = nic->ip_filter_tbl_size; ++ table_offset = RX_FILTER_TBL0_OFST; ++ table_stride = 2 * FALCON_REGISTER128; ++ ++ for (i = 0; i < filter_tbl_size; i++) { ++ if (!filter_is_active(nic, type, i)) ++ continue; ++ ++ spec = filter_spec_cache_entry(nic, type, i); ++ ++ build_filter(nic, spec, &dummy_key, &dummy_tbl_size, ++ &dummy_depth, &q0_expect, &q1_expect); ++ ++ falcon_read_qq(EFHW_KVA(nic) + table_offset + i * table_stride, ++ &q0_got, &q1_got); ++ ++ if ((q0_got != q0_expect) || (q1_got != q1_expect)) { ++ falcon_write_qq(EFHW_KVA(nic) + 0x300, ++ q0_got, q1_got); ++ EFHW_ERR("ERROR: RX-filter[%d][%d] was " ++ "%"PRIx64":%" PRIx64" expected " ++ "%"PRIx64":%"PRIx64, ++ nic->index, i, q0_got, q1_got, ++ q0_expect, q1_expect); ++ } ++ } ++} ++#endif ++ ++ ++static void write_filter_table_entry(struct efhw_nic *nic, ++ unsigned filter_idx, ++ uint64_t q0, uint64_t q1) ++{ ++ unsigned table_offset, table_stride, offset; ++ ++ EFHW_ASSERT(filter_idx < nic->ip_filter_tbl_size); ++ table_offset = RX_FILTER_TBL0_OFST; ++ table_stride = 2 * FALCON_REGISTER128; ++ ++ offset = table_offset + filter_idx * table_stride; ++ falcon_write_qq(EFHW_KVA(nic) + offset, q0, q1); ++ mmiowb(); ++ ++#if FALCON_VERIFY_FILTERS ++ { ++ uint64_t q0read, q1read; ++ ++ /* Read a different entry first - ensure BIU flushed shadow */ ++ falcon_read_qq(EFHW_KVA(nic) + offset + 0x10, &q0read, &q1read); ++ falcon_read_qq(EFHW_KVA(nic) + offset, &q0read, &q1read); ++ EFHW_ASSERT(q0read == q0); ++ EFHW_ASSERT(q1read == q1); ++ ++ verify_filters(nic, type); ++ } ++#endif ++} ++ ++ ++static int falcon_nic_filter_set(struct efhw_nic *nic, ++ struct efhw_filter_spec *spec, ++ int *filter_idx_out) ++{ ++ FALCON_LOCK_DECL; ++ unsigned key = 0, tbl_size = 0, hash1, hash2, k; ++ struct efhw_filter_depth *depth = NULL; ++ int filter_idx = -1; ++ int rc = 0; ++ uint64_t q0, q1; ++ ++ build_filter(nic, spec, &key, &tbl_size, &depth, &q0, &q1); ++ ++ if (tbl_size == 0) ++ return -EINVAL; ++ ++ EFHW_TRACE("%s: depth->max=%d", __func__, depth->max); ++ ++ hash1 = falcon_hash_function1(key, tbl_size); ++ hash2 = falcon_hash_function2(key, tbl_size); ++ ++ FALCON_LOCK_LOCK(nic); ++ ++ for (k = 0; k < depth->max; k++) { ++ filter_idx = falcon_hash_iterator(hash1, hash2, k, tbl_size); ++ if (!filter_is_active(nic, filter_idx)) ++ break; ++#if FALCON_FULL_FILTER_CACHE ++ if (filter_is_duplicate(nic, spec, filter_idx)) { ++ EFHW_WARN("%s: ERROR: duplicate filter (disabling " ++ "interrupts)", __func__); ++ falcon_nic_interrupt_hw_disable(nic); ++ rc = -EINVAL; ++ goto fail1; ++ } ++#endif ++ } ++ if (k == depth->max) { ++ rc = -EADDRINUSE; ++ filter_idx = -1; ++ goto fail1; ++ } else if (depth->needed < (k + 1)) { ++ depth->needed = k + 1; ++ } ++ ++ EFHW_ASSERT(filter_idx < (int)tbl_size); ++ ++ set_filter_cache_entry(nic, spec, filter_idx); ++ write_filter_table_entry(nic, filter_idx, q0, q1); ++ ++ ++nic->ip_filter_tbl_used; ++ ++ *filter_idx_out = filter_idx; ++ ++ EFHW_TRACE("%s: filter index %d rxq %u set in %u", ++ __func__, filter_idx, spec->dmaq_id, k); ++ ++fail1: ++ FALCON_LOCK_UNLOCK(nic); ++ return rc; ++} ++ ++ ++static void falcon_nic_filter_clear(struct efhw_nic *nic, ++ int filter_idx) ++{ ++ FALCON_LOCK_DECL; ++ ++ if (filter_idx < 0) ++ return; ++ ++ FALCON_LOCK_LOCK(nic); ++ if (filter_is_active(nic, filter_idx)) { ++ if (--nic->ip_filter_tbl_used == 0) { ++ nic->tcp_full_srch.needed = 0; ++ nic->tcp_wild_srch.needed = 0; ++ nic->udp_full_srch.needed = 0; ++ nic->udp_wild_srch.needed = 0; ++ } ++ } ++ clear_filter_cache_entry(nic, filter_idx); ++ write_filter_table_entry(nic, filter_idx, 0, 0); ++ FALCON_LOCK_UNLOCK(nic); ++} ++ ++ ++int ++falcon_nic_filter_ctor(struct efhw_nic *nic) ++{ ++ nic->ip_filter_tbl_size = 8 * 1024; ++ nic->ip_filter_tbl_used = 0; ++ ++ nic->tcp_full_srch.needed = 0; ++ nic->tcp_full_srch.max = RX_FILTER_CTL_SRCH_LIMIT_TCP_FULL ++ - RX_FILTER_CTL_SRCH_FUDGE_FULL; ++ nic->tcp_wild_srch.needed = 0; ++ nic->tcp_wild_srch.max = RX_FILTER_CTL_SRCH_LIMIT_TCP_WILD ++ - RX_FILTER_CTL_SRCH_FUDGE_WILD; ++ nic->udp_full_srch.needed = 0; ++ nic->udp_full_srch.max = RX_FILTER_CTL_SRCH_LIMIT_UDP_FULL ++ - RX_FILTER_CTL_SRCH_FUDGE_FULL; ++ nic->udp_wild_srch.needed = 0; ++ nic->udp_wild_srch.max = RX_FILTER_CTL_SRCH_LIMIT_UDP_WILD ++ - RX_FILTER_CTL_SRCH_FUDGE_WILD; ++ ++ nic->filter_in_use = vmalloc(FALCON_FILTER_TBL_NUM); ++ if (nic->filter_in_use == NULL) ++ return -ENOMEM; ++ memset(nic->filter_in_use, 0, FALCON_FILTER_TBL_NUM); ++#if FALCON_FULL_FILTER_CACHE ++ nic->filter_spec_cache = vmalloc(FALCON_FILTER_TBL_NUM ++ * sizeof(struct efhw_filter_spec)); ++ if (nic->filter_spec_cache == NULL) ++ return -ENOMEM; ++ memset(nic->filter_spec_cache, 0, FALCON_FILTER_TBL_NUM ++ * sizeof(struct efhw_filter_spec)); ++#endif ++ ++ return 0; ++} ++ ++ ++void ++falcon_nic_filter_dtor(struct efhw_nic *nic) ++{ ++#if FALCON_FULL_FILTER_CACHE ++ if (nic->filter_spec_cache) ++ vfree(nic->filter_spec_cache); ++#endif ++ if (nic->filter_in_use) ++ vfree(nic->filter_in_use); ++} ++ ++ ++/*-------------------------------------------------------------------- ++ * ++ * Compatibility with old filter API ++ * ++ *--------------------------------------------------------------------*/ ++ ++void ++falcon_nic_rx_filter_ctl_get(struct efhw_nic *nic, uint32_t *tcp_full, ++ uint32_t *tcp_wild, ++ uint32_t *udp_full, uint32_t *udp_wild) ++{ ++ struct efhw_filter_search_limits lim; ++ ++ falcon_nic_get_rx_filter_search_limits(nic, &lim, 0); ++ *tcp_full = (uint32_t)lim.tcp_full; ++ *tcp_wild = (uint32_t)lim.tcp_wild; ++ *udp_full = (uint32_t)lim.udp_full; ++ *udp_wild = (uint32_t)lim.udp_wild; ++} ++EXPORT_SYMBOL(falcon_nic_rx_filter_ctl_get); ++ ++ ++void ++falcon_nic_rx_filter_ctl_set(struct efhw_nic *nic, uint32_t tcp_full, ++ uint32_t tcp_wild, ++ uint32_t udp_full, uint32_t udp_wild) ++{ ++ struct efhw_filter_search_limits lim; ++ ++ lim.tcp_full = (unsigned)tcp_full; ++ lim.tcp_wild = (unsigned)tcp_wild; ++ lim.udp_full = (unsigned)udp_full; ++ lim.udp_wild = (unsigned)udp_wild; ++ falcon_nic_set_rx_filter_search_limits(nic, &lim, 0); ++} ++EXPORT_SYMBOL(falcon_nic_rx_filter_ctl_set); ++ ++ ++static int ++falcon_nic_ipfilter_set(struct efhw_nic *nic, int type, int *_filter_idx, ++ int dmaq, ++ unsigned saddr_be32, unsigned sport_be16, ++ unsigned daddr_be32, unsigned dport_be16) ++{ ++ struct efhw_filter_spec spec; ++ ++ spec.dmaq_id = dmaq; ++ spec.saddr_le32 = ntohl(saddr_be32); ++ spec.daddr_le32 = ntohl(daddr_be32); ++ spec.sport_le16 = ntohs((unsigned short) sport_be16); ++ spec.dport_le16 = ntohs((unsigned short) dport_be16); ++ spec.tcp = ((type & EFHW_IP_FILTER_TYPE_TCP_MASK) != 0); ++ spec.full = ((type & EFHW_IP_FILTER_TYPE_FULL_MASK) != 0); ++ spec.rss = ((type & EFHW_IP_FILTER_TYPE_RSS_B0_MASK) != 0); ++ spec.scatter = ((type & EFHW_IP_FILTER_TYPE_NOSCAT_B0_MASK) == 0); ++ return falcon_nic_filter_set(nic, &spec, _filter_idx); ++} ++ ++static void falcon_nic_ipfilter_clear(struct efhw_nic *nic, int filter_idx) ++{ ++ falcon_nic_filter_clear(nic, filter_idx); ++} ++ ++ ++/*-------------------------------------------------------------------- ++ * ++ * Abstraction Layer Hooks ++ * ++ *--------------------------------------------------------------------*/ ++ ++struct efhw_func_ops falcon_char_functional_units = { ++ falcon_nic_close_hardware, ++ falcon_nic_init_hardware, ++ falcon_nic_interrupt, ++ falcon_nic_interrupt_enable, ++ falcon_nic_interrupt_disable, ++ falcon_nic_set_interrupt_moderation, ++ falcon_nic_event_queue_enable, ++ falcon_nic_event_queue_disable, ++ falcon_nic_wakeup_request, ++ falcon_nic_sw_event, ++ falcon_nic_ipfilter_set, ++ falcon_nic_ipfilter_clear, ++ falcon_dmaq_tx_q_init, ++ falcon_dmaq_rx_q_init, ++ falcon_dmaq_tx_q_disable, ++ falcon_dmaq_rx_q_disable, ++ falcon_flush_tx_dma_channel, ++ falcon_flush_rx_dma_channel, ++ falcon_nic_buffer_table_set, ++ falcon_nic_buffer_table_set_n, ++ falcon_nic_buffer_table_clear, ++ falcon_nic_buffer_table_commit, ++ falcon_nic_filter_set, ++ falcon_nic_filter_clear, ++}; ++ ++ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/falcon_hash.c 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,159 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file contains EtherFabric NIC hash algorithms implementation. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#include ++#include ++ ++ ++static unsigned int ++common_get_ip_key(unsigned int src_ip, unsigned int src_port, ++ unsigned int dest_ip, unsigned int dest_port, ++ int tcp, int full, int tx, unsigned int masked_q_id) ++{ ++ ++ unsigned int tmp_port, result; ++ ++ EFHW_ASSERT(tcp == 0 || tcp == 1); ++ EFHW_ASSERT(full == 0 || full == 1); ++ EFHW_ASSERT(masked_q_id < (1 << 10)); ++ ++ /* m=masked_q_id(TX)/0(RX) u=UDP S,D=src/dest addr s,d=src/dest port ++ * ++ * Wildcard filters have src(TX)/dest(RX) addr and port = 0; ++ * and UDP wildcard filters have the src and dest port fields swapped. ++ * ++ * Addr/port fields are little-endian. ++ * ++ * 3322222222221111111111 ++ * 10987654321098765432109876543210 ++ * ++ * 000000000000000000000mmmmmmmmmmu ^ ++ * DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD ^ ++ * ddddddddddddddddSSSSSSSSSSSSSSSS ^ ++ * SSSSSSSSSSSSSSSSssssssssssssssss ++ */ ++ ++ if (!tx) ++ masked_q_id = 0; ++ ++ if (!full) { ++ if (tx) { ++ dest_ip = 0; ++ dest_port = 0; ++ } else { ++ src_ip = 0; ++ src_port = 0; ++ } ++ if (!tcp) { ++ tmp_port = src_port; ++ src_port = dest_port; ++ dest_port = tmp_port; ++ } ++ } ++ ++ result = ((masked_q_id << 1) | (!tcp)) ^ ++ (dest_ip) ^ ++ (((dest_port & 0xffff) << 16) | ((src_ip >> 16) & 0xffff)) ^ ++ (((src_ip & 0xffff) << 16) | (src_port & 0xffff)); ++ ++ EFHW_TRACE("%s: IP %s %s %x", __func__, tcp ? "TCP" : "UDP", ++ full ? "Full" : "Wildcard", result); ++ ++ return result; ++} ++ ++ ++unsigned int ++falcon_hash_get_ip_key(unsigned int src_ip, unsigned int src_port, ++ unsigned int dest_ip, unsigned int dest_port, ++ int tcp, int full) ++{ ++ return common_get_ip_key(src_ip, src_port, dest_ip, dest_port, tcp, ++ full, 0, 0); ++} ++ ++ ++/* This function generates the First Hash key */ ++unsigned int falcon_hash_function1(unsigned int key, unsigned int nfilters) ++{ ++ ++ unsigned short int lfsr_reg; ++ unsigned int tmp_key; ++ int index; ++ ++ unsigned short int lfsr_input; ++ unsigned short int single_bit_key; ++ unsigned short int bit16_lfsr; ++ unsigned short int bit3_lfsr; ++ ++ lfsr_reg = 0xFFFF; ++ tmp_key = key; ++ ++ /* For Polynomial equation X^16+X^3+1 */ ++ for (index = 0; index < 32; index++) { ++ /* Get the bit from key and shift the key */ ++ single_bit_key = (tmp_key & 0x80000000) >> 31; ++ tmp_key = tmp_key << 1; ++ ++ /* get the Tap bits to XOR operation */ ++ bit16_lfsr = (lfsr_reg & 0x8000) >> 15; ++ bit3_lfsr = (lfsr_reg & 0x0004) >> 2; ++ ++ /* Get the Input value to the LFSR */ ++ lfsr_input = ((bit16_lfsr ^ bit3_lfsr) ^ single_bit_key); ++ ++ /* Shift and store out of the two TAPs */ ++ lfsr_reg = lfsr_reg << 1; ++ lfsr_reg = lfsr_reg | (lfsr_input & 0x0001); ++ ++ } ++ ++ lfsr_reg = lfsr_reg & (nfilters - 1); ++ ++ return lfsr_reg; ++} ++ ++/* This function generates the Second Hash */ ++unsigned int ++falcon_hash_function2(unsigned int key, unsigned int nfilters) ++{ ++ return (unsigned int)(((unsigned long long)key * 2 - 1) & ++ (nfilters - 1)); ++} ++ ++/* This function iterates through the hash table */ ++unsigned int ++falcon_hash_iterator(unsigned int hash1, unsigned int hash2, ++ unsigned int n_search, unsigned int nfilters) ++{ ++ return (hash1 + (n_search * hash2)) & (nfilters - 1); ++} ++ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/filter_resource.c 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,250 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file contains filters support. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * Certain parts of the driver were implemented by ++ * Alexandra Kossovsky ++ * OKTET Labs Ltd, Russia, ++ * http://oktetlabs.ru, ++ * by request of Solarflare Communications ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "efrm_internal.h" ++ ++ ++struct filter_resource_manager { ++ struct efrm_resource_manager rm; ++ struct kfifo *free_ids; ++}; ++ ++static struct filter_resource_manager *efrm_filter_manager; ++ ++ ++void efrm_filter_resource_free(struct filter_resource *frs) ++{ ++ struct efhw_nic *nic = frs->rs.rs_client->nic; ++ int id; ++ ++ EFRM_RESOURCE_ASSERT_VALID(&frs->rs, 1); ++ ++ EFRM_TRACE("%s: " EFRM_RESOURCE_FMT, __func__, ++ EFRM_RESOURCE_PRI_ARG(frs->rs.rs_handle)); ++ ++ efhw_nic_ipfilter_clear(nic, frs->filter_idx); ++ frs->filter_idx = -1; ++ efrm_vi_resource_release(frs->pt); ++ ++ /* Free this filter. */ ++ id = EFRM_RESOURCE_INSTANCE(frs->rs.rs_handle); ++ EFRM_VERIFY_EQ(kfifo_put(efrm_filter_manager->free_ids, ++ (unsigned char *)&id, sizeof(id)), ++ sizeof(id)); ++ ++ efrm_client_put(frs->rs.rs_client); ++ EFRM_DO_DEBUG(memset(frs, 0, sizeof(*frs))); ++ kfree(frs); ++} ++EXPORT_SYMBOL(efrm_filter_resource_free); ++ ++ ++void efrm_filter_resource_release(struct filter_resource *frs) ++{ ++ if (__efrm_resource_release(&frs->rs)) ++ efrm_filter_resource_free(frs); ++} ++EXPORT_SYMBOL(efrm_filter_resource_release); ++ ++ ++static void filter_rm_dtor(struct efrm_resource_manager *rm) ++{ ++ EFRM_TRACE("%s:", __func__); ++ ++ EFRM_RESOURCE_MANAGER_ASSERT_VALID(&efrm_filter_manager->rm); ++ EFRM_ASSERT(&efrm_filter_manager->rm == rm); ++ ++ kfifo_vfree(efrm_filter_manager->free_ids); ++ EFRM_TRACE("%s: done", __func__); ++} ++ ++/**********************************************************************/ ++/**********************************************************************/ ++/**********************************************************************/ ++ ++int efrm_create_filter_resource_manager(struct efrm_resource_manager **rm_out) ++{ ++ int rc; ++ ++ EFRM_ASSERT(rm_out); ++ ++ efrm_filter_manager = ++ kmalloc(sizeof(struct filter_resource_manager), GFP_KERNEL); ++ if (efrm_filter_manager == 0) ++ return -ENOMEM; ++ memset(efrm_filter_manager, 0, sizeof(*efrm_filter_manager)); ++ ++ rc = efrm_resource_manager_ctor(&efrm_filter_manager->rm, ++ filter_rm_dtor, "FILTER", ++ EFRM_RESOURCE_FILTER); ++ if (rc < 0) ++ goto fail1; ++ ++ /* Create a pool of free instances */ ++ rc = efrm_kfifo_id_ctor(&efrm_filter_manager->free_ids, ++ 0, EFHW_IP_FILTER_NUM, ++ &efrm_filter_manager->rm.rm_lock); ++ if (rc != 0) ++ goto fail2; ++ ++ *rm_out = &efrm_filter_manager->rm; ++ EFRM_TRACE("%s: filter resources created - %d IDs", ++ __func__, kfifo_len(efrm_filter_manager->free_ids)); ++ return 0; ++ ++fail2: ++ efrm_resource_manager_dtor(&efrm_filter_manager->rm); ++fail1: ++ memset(efrm_filter_manager, 0, sizeof(*efrm_filter_manager)); ++ kfree(efrm_filter_manager); ++ return rc; ++ ++} ++ ++ ++int efrm_filter_resource_clear(struct filter_resource *frs) ++{ ++ struct efhw_nic *nic = frs->rs.rs_client->nic; ++ ++ efhw_nic_ipfilter_clear(nic, frs->filter_idx); ++ frs->filter_idx = -1; ++ return 0; ++} ++EXPORT_SYMBOL(efrm_filter_resource_clear); ++ ++ ++int ++__efrm_filter_resource_set(struct filter_resource *frs, int type, ++ unsigned saddr, uint16_t sport, ++ unsigned daddr, uint16_t dport) ++{ ++ struct efhw_nic *nic = frs->rs.rs_client->nic; ++ int vi_instance; ++ ++ EFRM_ASSERT(frs); ++ ++ if (efrm_nic_tablep->a_nic->devtype.variant >= 'B' && ++ (frs->pt->flags & EFHW_VI_JUMBO_EN) == 0) ++ type |= EFHW_IP_FILTER_TYPE_NOSCAT_B0_MASK; ++ vi_instance = EFRM_RESOURCE_INSTANCE(frs->pt->rs.rs_handle); ++ ++ return efhw_nic_ipfilter_set(nic, type, &frs->filter_idx, ++ vi_instance, saddr, sport, daddr, dport); ++} ++EXPORT_SYMBOL(__efrm_filter_resource_set);; ++ ++ ++int ++efrm_filter_resource_alloc(struct vi_resource *vi_parent, ++ struct filter_resource **frs_out) ++{ ++ struct filter_resource *frs; ++ int rc, instance; ++ ++ EFRM_ASSERT(frs_out); ++ EFRM_ASSERT(efrm_filter_manager); ++ EFRM_RESOURCE_MANAGER_ASSERT_VALID(&efrm_filter_manager->rm); ++ EFRM_ASSERT(vi_parent != NULL); ++ EFRM_ASSERT(EFRM_RESOURCE_TYPE(vi_parent->rs.rs_handle) == ++ EFRM_RESOURCE_VI); ++ ++ /* Allocate resource data structure. */ ++ frs = kmalloc(sizeof(struct filter_resource), GFP_KERNEL); ++ if (!frs) ++ return -ENOMEM; ++ ++ /* Allocate an instance. */ ++ rc = kfifo_get(efrm_filter_manager->free_ids, ++ (unsigned char *)&instance, sizeof(instance)); ++ if (rc != sizeof(instance)) { ++ EFRM_TRACE("%s: out of instances", __func__); ++ EFRM_ASSERT(rc == 0); ++ rc = -EBUSY; ++ goto fail1; ++ } ++ ++ /* Initialise the resource DS. */ ++ efrm_resource_init(&frs->rs, EFRM_RESOURCE_FILTER, instance); ++ frs->pt = vi_parent; ++ efrm_resource_ref(&frs->pt->rs); ++ frs->filter_idx = -1; ++ ++ EFRM_TRACE("%s: " EFRM_RESOURCE_FMT " VI %d", __func__, ++ EFRM_RESOURCE_PRI_ARG(frs->rs.rs_handle), ++ EFRM_RESOURCE_INSTANCE(vi_parent->rs.rs_handle)); ++ ++ efrm_client_add_resource(vi_parent->rs.rs_client, &frs->rs); ++ *frs_out = frs; ++ return 0; ++ ++fail1: ++ memset(frs, 0, sizeof(*frs)); ++ kfree(frs); ++ return rc; ++} ++EXPORT_SYMBOL(efrm_filter_resource_alloc); ++ ++ ++int efrm_filter_resource_instance(struct filter_resource *frs) ++{ ++ return EFRM_RESOURCE_INSTANCE(frs->rs.rs_handle); ++} ++EXPORT_SYMBOL(efrm_filter_resource_instance); ++ ++ ++struct efrm_resource * ++efrm_filter_resource_to_resource(struct filter_resource *frs) ++{ ++ return &frs->rs; ++} ++EXPORT_SYMBOL(efrm_filter_resource_to_resource); ++ ++ ++struct filter_resource * ++efrm_filter_resource_from_resource(struct efrm_resource *rs) ++{ ++ return filter_resource(rs); ++} ++EXPORT_SYMBOL(efrm_filter_resource_from_resource); +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/iobufset_resource.c 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,404 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file contains non-contiguous I/O buffers support. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * Certain parts of the driver were implemented by ++ * Alexandra Kossovsky ++ * OKTET Labs Ltd, Russia, ++ * http://oktetlabs.ru, ++ * by request of Solarflare Communications ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "efrm_internal.h" ++ ++ ++#define EFRM_IOBUFSET_MAX_NUM_INSTANCES 0x00010000 ++ ++struct iobufset_resource_manager { ++ struct efrm_resource_manager rm; ++ struct kfifo *free_ids; ++}; ++ ++struct iobufset_resource_manager *efrm_iobufset_manager; ++ ++#define iobsrs(rs1) iobufset_resource(rs1) ++ ++/* Returns size of iobufset resource data structure. */ ++static inline size_t iobsrs_size(int n_pages) ++{ ++ return offsetof(struct iobufset_resource, bufs) + ++ n_pages * sizeof(struct efhw_iopage); ++} ++ ++void efrm_iobufset_resource_free(struct iobufset_resource *rs) ++{ ++ unsigned int i; ++ int id; ++ ++ EFRM_RESOURCE_ASSERT_VALID(&rs->rs, 1); ++ ++ if (!rs->linked && rs->buf_tbl_alloc.base != (unsigned) -1) ++ efrm_buffer_table_free(&rs->buf_tbl_alloc); ++ ++ /* see comment on call to efhw_iopage_alloc in the alloc routine above ++ for discussion on use of efrm_nic_tablep->a_nic here */ ++ EFRM_ASSERT(efrm_nic_tablep->a_nic); ++ if (rs->linked) { ++ /* Nothing to do. */ ++ } else if (rs->chunk_order == 0) { ++ for (i = 0; i < rs->n_bufs; ++i) ++ efhw_iopage_free(efrm_nic_tablep->a_nic, &rs->bufs[i]); ++ } else { ++ /* it is important that this is executed in increasing page ++ * order because some implementations of ++ * efhw_iopages_init_from_iopage() assume this */ ++ for (i = 0; i < rs->n_bufs; ++ i += rs->pages_per_contiguous_chunk) { ++ struct efhw_iopages iopages; ++ efhw_iopages_init_from_iopage(&iopages, &rs->bufs[i], ++ rs->chunk_order); ++ efhw_iopages_free(efrm_nic_tablep->a_nic, &iopages); ++ } ++ } ++ ++ /* free the instance number */ ++ id = EFRM_RESOURCE_INSTANCE(rs->rs.rs_handle); ++ EFRM_VERIFY_EQ(kfifo_put(efrm_iobufset_manager->free_ids, ++ (unsigned char *)&id, sizeof(id)), sizeof(id)); ++ ++ efrm_vi_resource_release(rs->evq); ++ if (rs->linked) ++ efrm_iobufset_resource_release(rs->linked); ++ ++ efrm_client_put(rs->rs.rs_client); ++ if (iobsrs_size(rs->n_bufs) < PAGE_SIZE) { ++ EFRM_DO_DEBUG(memset(rs, 0, sizeof(*rs))); ++ kfree(rs); ++ } else { ++ EFRM_DO_DEBUG(memset(rs, 0, sizeof(*rs))); ++ vfree(rs); ++ } ++} ++EXPORT_SYMBOL(efrm_iobufset_resource_free); ++ ++ ++void efrm_iobufset_resource_release(struct iobufset_resource *iobrs) ++{ ++ if (__efrm_resource_release(&iobrs->rs)) ++ efrm_iobufset_resource_free(iobrs); ++} ++EXPORT_SYMBOL(efrm_iobufset_resource_release); ++ ++ ++ ++int ++efrm_iobufset_resource_alloc(int32_t n_pages, ++ int32_t pages_per_contiguous_chunk, ++ struct vi_resource *vi_evq, ++ struct iobufset_resource *linked, ++ bool phys_addr_mode, ++ struct iobufset_resource **iobrs_out) ++{ ++ struct iobufset_resource *iobrs; ++ int rc, instance, object_size; ++ unsigned int i; ++ ++ EFRM_ASSERT(iobrs_out); ++ EFRM_ASSERT(efrm_iobufset_manager); ++ EFRM_RESOURCE_MANAGER_ASSERT_VALID(&efrm_iobufset_manager->rm); ++ EFRM_RESOURCE_ASSERT_VALID(&vi_evq->rs, 0); ++ EFRM_ASSERT(EFRM_RESOURCE_TYPE(vi_evq->rs.rs_handle) == ++ EFRM_RESOURCE_VI); ++ EFRM_ASSERT(efrm_nic_tablep->a_nic); ++ ++ if (linked) { ++ /* This resource will share properties and memory with ++ * another. Only difference is that we'll program it into ++ * the buffer table of another nic. ++ */ ++ n_pages = linked->n_bufs; ++ pages_per_contiguous_chunk = linked->pages_per_contiguous_chunk; ++ phys_addr_mode = linked->buf_tbl_alloc.base == (unsigned) -1; ++ } ++ ++ /* allocate the resource data structure. */ ++ object_size = iobsrs_size(n_pages); ++ if (object_size < PAGE_SIZE) { ++ /* this should be OK from a tasklet */ ++ /* Necessary to do atomic alloc() as this ++ can be called from a weird-ass iSCSI context that is ++ !in_interrupt but is in_atomic - See BUG3163 */ ++ iobrs = kmalloc(object_size, GFP_ATOMIC); ++ } else { /* can't do this within a tasklet */ ++#ifndef NDEBUG ++ if (in_interrupt() || in_atomic()) { ++ EFRM_ERR("%s(): alloc->u.iobufset.in_n_pages=%d", ++ __func__, n_pages); ++ EFRM_ASSERT(!in_interrupt()); ++ EFRM_ASSERT(!in_atomic()); ++ } ++#endif ++ iobrs = (struct iobufset_resource *) vmalloc(object_size); ++ } ++ if (iobrs == NULL) { ++ EFRM_WARN("%s: failed to allocate container", __func__); ++ rc = -ENOMEM; ++ goto fail1; ++ } ++ ++ /* Allocate an instance number. */ ++ rc = kfifo_get(efrm_iobufset_manager->free_ids, ++ (unsigned char *)&instance, sizeof(instance)); ++ if (rc != sizeof(instance)) { ++ EFRM_WARN("%s: out of instances", __func__); ++ EFRM_ASSERT(rc == 0); ++ rc = -EBUSY; ++ goto fail3; ++ } ++ ++ efrm_resource_init(&iobrs->rs, EFRM_RESOURCE_IOBUFSET, instance); ++ ++ iobrs->evq = vi_evq; ++ iobrs->linked = linked; ++ iobrs->n_bufs = n_pages; ++ iobrs->pages_per_contiguous_chunk = pages_per_contiguous_chunk; ++ iobrs->chunk_order = fls(iobrs->pages_per_contiguous_chunk - 1); ++ iobrs->buf_tbl_alloc.base = (unsigned) -1; ++ ++ EFRM_TRACE("%s: " EFRM_RESOURCE_FMT " %u pages", __func__, ++ EFRM_RESOURCE_PRI_ARG(iobrs->rs.rs_handle), iobrs->n_bufs); ++ ++ /* Allocate the iobuffers. */ ++ if (linked) { ++ memcpy(iobrs->bufs, linked->bufs, ++ iobrs->n_bufs * sizeof(iobrs->bufs[0])); ++ } else if (iobrs->chunk_order == 0) { ++ memset(iobrs->bufs, 0, iobrs->n_bufs * sizeof(iobrs->bufs[0])); ++ for (i = 0; i < iobrs->n_bufs; ++i) { ++ /* due to bug2426 we have to specifiy a NIC when ++ * allocating a DMAable page, which is a bit messy. ++ * For now we assume that if the page is suitable ++ * (e.g. DMAable) by one nic (efrm_nic_tablep->a_nic), ++ * it is suitable for all NICs. ++ * XXX I bet that breaks in Solaris. ++ */ ++ rc = efhw_iopage_alloc(efrm_nic_tablep->a_nic, ++ &iobrs->bufs[i]); ++ if (rc < 0) { ++ EFRM_WARN("%s: failed (rc %d) to allocate " ++ "page (i=%u)", __func__, rc, i); ++ goto fail4; ++ } ++ } ++ } else { ++ struct efhw_iopages iopages; ++ unsigned j; ++ ++ memset(iobrs->bufs, 0, iobrs->n_bufs * sizeof(iobrs->bufs[0])); ++ for (i = 0; i < iobrs->n_bufs; ++ i += iobrs->pages_per_contiguous_chunk) { ++ rc = efhw_iopages_alloc(efrm_nic_tablep->a_nic, ++ &iopages, iobrs->chunk_order); ++ if (rc < 0) { ++ EFRM_WARN("%s: failed (rc %d) to allocate " ++ "pages (i=%u order %d)", ++ __func__, rc, i, ++ iobrs->chunk_order); ++ goto fail4; ++ } ++ for (j = 0; j < iobrs->pages_per_contiguous_chunk; ++ j++) { ++ /* some implementation of ++ * efhw_iopage_init_from_iopages() rely on ++ * this function being called for ++ * _all_ pages in the chunk */ ++ efhw_iopage_init_from_iopages( ++ &iobrs->bufs[i + j], ++ &iopages, j); ++ } ++ } ++ } ++ ++ if (!phys_addr_mode) { ++ unsigned owner_id = EFAB_VI_RESOURCE_INSTANCE(iobrs->evq); ++ ++ if (!linked) { ++ /* Allocate space in the NIC's buffer table. */ ++ rc = efrm_buffer_table_alloc(fls(iobrs->n_bufs - 1), ++ &iobrs->buf_tbl_alloc); ++ if (rc < 0) { ++ EFRM_WARN("%s: failed (%d) to alloc %d buffer " ++ "table entries", __func__, rc, ++ iobrs->n_bufs); ++ goto fail5; ++ } ++ EFRM_ASSERT(((unsigned)1 << iobrs->buf_tbl_alloc.order) ++ >= (unsigned) iobrs->n_bufs); ++ } else { ++ iobrs->buf_tbl_alloc = linked->buf_tbl_alloc; ++ } ++ ++ /* Initialise the buffer table entries. */ ++ for (i = 0; i < iobrs->n_bufs; ++i) { ++ /*\ ?? \TODO burst them! */ ++ efrm_buffer_table_set(&iobrs->buf_tbl_alloc, ++ vi_evq->rs.rs_client->nic, ++ i, ++ efhw_iopage_dma_addr(&iobrs-> ++ bufs[i]), ++ owner_id); ++ } ++ efrm_buffer_table_commit(); ++ } ++ ++ EFRM_TRACE("%s: " EFRM_RESOURCE_FMT " %d pages @ " ++ EFHW_BUFFER_ADDR_FMT, __func__, ++ EFRM_RESOURCE_PRI_ARG(iobrs->rs.rs_handle), ++ iobrs->n_bufs, EFHW_BUFFER_ADDR(iobrs->buf_tbl_alloc.base, ++ 0)); ++ efrm_resource_ref(&iobrs->evq->rs); ++ if (linked != NULL) ++ efrm_resource_ref(&linked->rs); ++ efrm_client_add_resource(vi_evq->rs.rs_client, &iobrs->rs); ++ *iobrs_out = iobrs; ++ return 0; ++ ++fail5: ++ i = iobrs->n_bufs; ++fail4: ++ /* see comment on call to efhw_iopage_alloc above for a discussion ++ * on use of efrm_nic_tablep->a_nic here */ ++ if (linked) { ++ /* Nothing to do. */ ++ } else if (iobrs->chunk_order == 0) { ++ while (i--) { ++ struct efhw_iopage *page = &iobrs->bufs[i]; ++ efhw_iopage_free(efrm_nic_tablep->a_nic, page); ++ } ++ } else { ++ unsigned int j; ++ for (j = 0; j < i; j += iobrs->pages_per_contiguous_chunk) { ++ struct efhw_iopages iopages; ++ ++ EFRM_ASSERT(j % iobrs->pages_per_contiguous_chunk ++ == 0); ++ /* it is important that this is executed in increasing ++ * page order because some implementations of ++ * efhw_iopages_init_from_iopage() assume this */ ++ efhw_iopages_init_from_iopage(&iopages, ++ &iobrs->bufs[j], ++ iobrs->chunk_order); ++ efhw_iopages_free(efrm_nic_tablep->a_nic, &iopages); ++ } ++ } ++fail3: ++ if (object_size < PAGE_SIZE) ++ kfree(iobrs); ++ else ++ vfree(iobrs); ++fail1: ++ return rc; ++} ++EXPORT_SYMBOL(efrm_iobufset_resource_alloc); ++ ++static void iobufset_rm_dtor(struct efrm_resource_manager *rm) ++{ ++ EFRM_ASSERT(&efrm_iobufset_manager->rm == rm); ++ kfifo_vfree(efrm_iobufset_manager->free_ids); ++} ++ ++int ++efrm_create_iobufset_resource_manager(struct efrm_resource_manager **rm_out) ++{ ++ int rc, max; ++ ++ EFRM_ASSERT(rm_out); ++ ++ efrm_iobufset_manager = ++ kmalloc(sizeof(*efrm_iobufset_manager), GFP_KERNEL); ++ if (efrm_iobufset_manager == 0) ++ return -ENOMEM; ++ memset(efrm_iobufset_manager, 0, sizeof(*efrm_iobufset_manager)); ++ ++ /* ++ * Bug 1145, 1370: We need to set initial size of both the resource ++ * table and instance id table so they never need to grow as we ++ * want to be allocate new iobufset at tasklet time. Lets make ++ * a pessimistic guess at maximum number of iobufsets possible. ++ * Could be less because ++ * - jumbo frames have same no of packets per iobufset BUT more ++ * pages per buffer ++ * - buffer table entries used independently of iobufsets by ++ * sendfile ++ * ++ * Based on TCP/IP stack setting of PKTS_PER_SET_S=5 ... ++ * - can't use this define here as it breaks the layering. ++ */ ++#define MIN_PAGES_PER_IOBUFSET (1 << 4) ++ ++ max = efrm_buffer_table_size() / MIN_PAGES_PER_IOBUFSET; ++ max = min_t(int, max, EFRM_IOBUFSET_MAX_NUM_INSTANCES); ++ ++ /* HACK: There currently exists an option to allocate buffers that ++ * are not programmed into the buffer table, so the max number is ++ * not limited by the buffer table size. I'm hoping this usage ++ * will go away eventually. ++ */ ++ max = 32768; ++ ++ rc = efrm_kfifo_id_ctor(&efrm_iobufset_manager->free_ids, ++ 0, max, &efrm_iobufset_manager->rm.rm_lock); ++ if (rc != 0) ++ goto fail1; ++ ++ rc = efrm_resource_manager_ctor(&efrm_iobufset_manager->rm, ++ iobufset_rm_dtor, "IOBUFSET", ++ EFRM_RESOURCE_IOBUFSET); ++ if (rc < 0) ++ goto fail2; ++ ++ *rm_out = &efrm_iobufset_manager->rm; ++ return 0; ++ ++fail2: ++ kfifo_vfree(efrm_iobufset_manager->free_ids); ++fail1: ++ EFRM_DO_DEBUG(memset(efrm_iobufset_manager, 0, ++ sizeof(*efrm_iobufset_manager))); ++ kfree(efrm_iobufset_manager); ++ return rc; ++} +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/iopage.c 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,103 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file provides Linux-specific implementation for iopage API used ++ * from efhw library. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#include ++#include "kernel_compat.h" ++#include /* for dma_addr_t */ ++ ++int efhw_iopage_alloc(struct efhw_nic *nic, struct efhw_iopage *p) ++{ ++ struct linux_efhw_nic *lnic = linux_efhw_nic(nic); ++ dma_addr_t handle; ++ void *kva; ++ ++ kva = efrm_pci_alloc_consistent(lnic->pci_dev, PAGE_SIZE, ++ &handle); ++ if (kva == 0) ++ return -ENOMEM; ++ ++ EFHW_ASSERT((handle & ~PAGE_MASK) == 0); ++ ++ memset((void *)kva, 0, PAGE_SIZE); ++ efhw_page_init_from_va(&p->p, kva); ++ ++ p->dma_addr = handle; ++ ++ return 0; ++} ++ ++void efhw_iopage_free(struct efhw_nic *nic, struct efhw_iopage *p) ++{ ++ struct linux_efhw_nic *lnic = linux_efhw_nic(nic); ++ EFHW_ASSERT(efhw_page_is_valid(&p->p)); ++ ++ efrm_pci_free_consistent(lnic->pci_dev, PAGE_SIZE, ++ efhw_iopage_ptr(p), p->dma_addr); ++} ++ ++int ++efhw_iopages_alloc(struct efhw_nic *nic, struct efhw_iopages *p, ++ unsigned order) ++{ ++ unsigned bytes = 1u << (order + PAGE_SHIFT); ++ struct linux_efhw_nic *lnic = linux_efhw_nic(nic); ++ dma_addr_t handle; ++ caddr_t addr; ++ int gfp_flag; ++ ++ /* Set __GFP_COMP if available to make reference counting work. ++ * This is recommended here: ++ * http://www.forbiddenweb.org/viewtopic.php?id=83167&page=4#348331 ++ */ ++ gfp_flag = ((in_atomic() ? GFP_ATOMIC : GFP_KERNEL) | __GFP_COMP); ++ addr = efrm_dma_alloc_coherent(&lnic->pci_dev->dev, bytes, &handle, ++ gfp_flag); ++ if (addr == NULL) ++ return -ENOMEM; ++ ++ EFHW_ASSERT((handle & ~PAGE_MASK) == 0); ++ ++ p->order = order; ++ p->dma_addr = handle; ++ p->kva = addr; ++ ++ return 0; ++} ++ ++void efhw_iopages_free(struct efhw_nic *nic, struct efhw_iopages *p) ++{ ++ unsigned bytes = 1u << (p->order + PAGE_SHIFT); ++ struct linux_efhw_nic *lnic = linux_efhw_nic(nic); ++ ++ efrm_dma_free_coherent(&lnic->pci_dev->dev, bytes, ++ (void *)p->kva, p->dma_addr); ++} +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/kernel_compat.c 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,118 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file provides compatibility layer for various Linux kernel versions ++ * (starting from 2.6.9 RHEL kernel). ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * Certain parts of the driver were implemented by ++ * Alexandra Kossovsky ++ * OKTET Labs Ltd, Russia, ++ * http://oktetlabs.ru, ++ * by request of Solarflare Communications ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#define IN_KERNEL_COMPAT_C ++#include ++#include ++#include "kernel_compat.h" ++ ++/* Set this to 1 to enable very basic counting of iopage(s) allocations, then ++ * call dump_iopage_counts() to show the number of current allocations of ++ * orders 0-7. ++ */ ++#define EFRM_IOPAGE_COUNTS_ENABLED 0 ++ ++ ++/**************************************************************************** ++ * ++ * allocate a buffer suitable for DMA to/from the NIC ++ * ++ ****************************************************************************/ ++ ++#if EFRM_IOPAGE_COUNTS_ENABLED ++ ++static int iopage_counts[8]; ++ ++void dump_iopage_counts(void) ++{ ++ EFRM_NOTICE("iopage counts: %d %d %d %d %d %d %d %d", iopage_counts[0], ++ iopage_counts[1], iopage_counts[2], iopage_counts[3], ++ iopage_counts[4], iopage_counts[5], iopage_counts[6], ++ iopage_counts[7]); ++} ++ ++#endif ++ ++ ++ ++/*********** pci_alloc_consistent / pci_free_consistent ***********/ ++ ++void *efrm_dma_alloc_coherent(struct device *dev, size_t size, ++ dma_addr_t *dma_addr, int flag) ++{ ++ void *ptr; ++ unsigned order; ++ ++ order = __ffs(size/PAGE_SIZE); ++ EFRM_ASSERT(size == (PAGE_SIZE< ++ * ++ * ++ * Certain parts of the driver were implemented by ++ * Alexandra Kossovsky ++ * OKTET Labs Ltd, Russia, ++ * http://oktetlabs.ru, ++ * by request of Solarflare Communications ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#ifndef DRIVER_LINUX_RESOURCE_KERNEL_COMPAT_H ++#define DRIVER_LINUX_RESOURCE_KERNEL_COMPAT_H ++ ++#include ++#include ++#include ++#include ++ ++/********* pci_map_*() ********************/ ++ ++extern void *efrm_dma_alloc_coherent(struct device *dev, size_t size, ++ dma_addr_t *dma_addr, int flag); ++ ++extern void efrm_dma_free_coherent(struct device *dev, size_t size, ++ void *ptr, dma_addr_t dma_addr); ++ ++static inline void *efrm_pci_alloc_consistent(struct pci_dev *hwdev, ++ size_t size, ++ dma_addr_t *dma_addr) ++{ ++ return efrm_dma_alloc_coherent(&hwdev->dev, size, dma_addr, ++ GFP_ATOMIC); ++} ++ ++static inline void efrm_pci_free_consistent(struct pci_dev *hwdev, size_t size, ++ void *ptr, dma_addr_t dma_addr) ++{ ++ efrm_dma_free_coherent(&hwdev->dev, size, ptr, dma_addr); ++} ++ ++ ++#endif /* DRIVER_LINUX_RESOURCE_KERNEL_COMPAT_H */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/kernel_proc.c 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,109 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file contains /proc/driver/sfc_resource/ implementation. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * Certain parts of the driver were implemented by ++ * Alexandra Kossovsky ++ * OKTET Labs Ltd, Russia, ++ * http://oktetlabs.ru, ++ * by request of Solarflare Communications ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#include ++#include ++#include ++ ++/** Top level directory for sfc specific stats **/ ++static struct proc_dir_entry *efrm_proc_root; /* = NULL */ ++ ++static int ++efrm_resource_read_proc(char *buf, char **start, off_t offset, int count, ++ int *eof, void *data); ++ ++int efrm_install_proc_entries(void) ++{ ++ /* create the top-level directory for etherfabric specific stuff */ ++ efrm_proc_root = proc_mkdir("driver/sfc_resource", NULL); ++ if (!efrm_proc_root) ++ return -ENOMEM; ++ ++ if (create_proc_read_entry("resources", 0, efrm_proc_root, ++ efrm_resource_read_proc, 0) == NULL) { ++ EFRM_WARN("%s: Unable to create /proc/drivers/sfc_resource/" ++ "resources", __func__); ++ } ++ return 0; ++} ++ ++void efrm_uninstall_proc_entries(void) ++{ ++ EFRM_ASSERT(efrm_proc_root); ++ remove_proc_entry("resources", efrm_proc_root); ++ remove_proc_entry(efrm_proc_root->name, efrm_proc_root->parent); ++ efrm_proc_root = NULL; ++} ++ ++/**************************************************************************** ++ * ++ * /proc/drivers/sfc/resources ++ * ++ ****************************************************************************/ ++ ++#define EFRM_PROC_PRINTF(buf, len, fmt, ...) \ ++ do { \ ++ if (count - len > 0) \ ++ len += snprintf(buf+len, count-len, (fmt), \ ++ __VA_ARGS__); \ ++ } while (0) ++ ++static int ++efrm_resource_read_proc(char *buf, char **start, off_t offset, int count, ++ int *eof, void *data) ++{ ++ irq_flags_t lock_flags; ++ int len = 0; ++ int type; ++ struct efrm_resource_manager *rm; ++ ++ for (type = 0; type < EFRM_RESOURCE_NUM; type++) { ++ rm = efrm_rm_table[type]; ++ if (rm == NULL) ++ continue; ++ ++ EFRM_PROC_PRINTF(buf, len, "*** %s ***\n", rm->rm_name); ++ ++ spin_lock_irqsave(&rm->rm_lock, lock_flags); ++ EFRM_PROC_PRINTF(buf, len, "current = %u\n", rm->rm_resources); ++ EFRM_PROC_PRINTF(buf, len, " max = %u\n\n", ++ rm->rm_resources_hiwat); ++ spin_unlock_irqrestore(&rm->rm_lock, lock_flags); ++ } ++ ++ return count ? strlen(buf) : 0; ++} +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/kfifo.c 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,208 @@ ++/* ++ * A simple kernel FIFO implementation. ++ * ++ * Copyright (C) 2004 Stelian Pop ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ */ ++ ++/* ++ * This file is stolen from the Linux kernel sources ++ * (linux-2.6.22/kernel/kfifo.c) into sfc_resource driver. ++ * It should be used for old kernels without kfifo implementation. ++ * Most part of linux/kfifo.h is incorporated into ++ * ci/efrm/sysdep_linux.h. ++ */ ++#include ++#ifdef HAS_NO_KFIFO ++ ++#include ++#include ++#include ++#include ++/*#include */ ++ ++/** ++ * kfifo_init - allocates a new FIFO using a preallocated buffer ++ * @buffer: the preallocated buffer to be used. ++ * @size: the size of the internal buffer, this have to be a power of 2. ++ * @gfp_mask: get_free_pages mask, passed to kmalloc() ++ * @lock: the lock to be used to protect the fifo buffer ++ * ++ * Do NOT pass the kfifo to kfifo_free() after use! Simply free the ++ * &struct kfifo with kfree(). ++ */ ++struct kfifo *kfifo_init(unsigned char *buffer, unsigned int size, ++ gfp_t gfp_mask, spinlock_t *lock) ++{ ++ struct kfifo *fifo; ++ ++ /* size must be a power of 2 */ ++ BUG_ON(size & (size - 1)); ++ ++ fifo = kmalloc(sizeof(struct kfifo), gfp_mask); ++ if (!fifo) ++ return ERR_PTR(-ENOMEM); ++ ++ fifo->buffer = buffer; ++ fifo->size = size; ++ fifo->in = fifo->out = 0; ++ fifo->lock = lock; ++ ++ return fifo; ++} ++EXPORT_SYMBOL(kfifo_init); ++ ++/** ++ * kfifo_alloc - allocates a new FIFO and its internal buffer ++ * @size: the size of the internal buffer to be allocated. ++ * @gfp_mask: get_free_pages mask, passed to kmalloc() ++ * @lock: the lock to be used to protect the fifo buffer ++ * ++ * The size will be rounded-up to a power of 2. ++ */ ++struct kfifo *kfifo_alloc(unsigned int size, gfp_t gfp_mask, spinlock_t *lock) ++{ ++ unsigned char *buffer; ++ struct kfifo *ret; ++ ++ /* ++ * round up to the next power of 2, since our 'let the indices ++ * wrap' tachnique works only in this case. ++ */ ++ if (size & (size - 1)) { ++ BUG_ON(size > 0x80000000); ++ size = roundup_pow_of_two(size); ++ } ++ ++ buffer = kmalloc(size, gfp_mask); ++ if (!buffer) ++ return ERR_PTR(-ENOMEM); ++ ++ ret = kfifo_init(buffer, size, gfp_mask, lock); ++ ++ if (IS_ERR(ret)) ++ kfree(buffer); ++ ++ return ret; ++} ++EXPORT_SYMBOL(kfifo_alloc); ++ ++/** ++ * kfifo_free - frees the FIFO ++ * @fifo: the fifo to be freed. ++ */ ++void kfifo_free(struct kfifo *fifo) ++{ ++ kfree(fifo->buffer); ++ kfree(fifo); ++} ++EXPORT_SYMBOL(kfifo_free); ++ ++/** ++ * __kfifo_put - puts some data into the FIFO, no locking version ++ * @fifo: the fifo to be used. ++ * @buffer: the data to be added. ++ * @len: the length of the data to be added. ++ * ++ * This function copies at most @len bytes from the @buffer into ++ * the FIFO depending on the free space, and returns the number of ++ * bytes copied. ++ * ++ * Note that with only one concurrent reader and one concurrent ++ * writer, you don't need extra locking to use these functions. ++ */ ++unsigned int ++__kfifo_put(struct kfifo *fifo, unsigned char *buffer, unsigned int len) ++{ ++ unsigned int l; ++ ++ len = min(len, fifo->size - fifo->in + fifo->out); ++ ++ /* ++ * Ensure that we sample the fifo->out index -before- we ++ * start putting bytes into the kfifo. ++ */ ++ ++ smp_mb(); ++ ++ /* first put the data starting from fifo->in to buffer end */ ++ l = min(len, fifo->size - (fifo->in & (fifo->size - 1))); ++ memcpy(fifo->buffer + (fifo->in & (fifo->size - 1)), buffer, l); ++ ++ /* then put the rest (if any) at the beginning of the buffer */ ++ memcpy(fifo->buffer, buffer + l, len - l); ++ ++ /* ++ * Ensure that we add the bytes to the kfifo -before- ++ * we update the fifo->in index. ++ */ ++ ++ smp_wmb(); ++ ++ fifo->in += len; ++ ++ return len; ++} ++EXPORT_SYMBOL(__kfifo_put); ++ ++/** ++ * __kfifo_get - gets some data from the FIFO, no locking version ++ * @fifo: the fifo to be used. ++ * @buffer: where the data must be copied. ++ * @len: the size of the destination buffer. ++ * ++ * This function copies at most @len bytes from the FIFO into the ++ * @buffer and returns the number of copied bytes. ++ * ++ * Note that with only one concurrent reader and one concurrent ++ * writer, you don't need extra locking to use these functions. ++ */ ++unsigned int ++__kfifo_get(struct kfifo *fifo, unsigned char *buffer, unsigned int len) ++{ ++ unsigned int l; ++ ++ len = min(len, fifo->in - fifo->out); ++ ++ /* ++ * Ensure that we sample the fifo->in index -before- we ++ * start removing bytes from the kfifo. ++ */ ++ ++ smp_rmb(); ++ ++ /* first get the data from fifo->out until the end of the buffer */ ++ l = min(len, fifo->size - (fifo->out & (fifo->size - 1))); ++ memcpy(buffer, fifo->buffer + (fifo->out & (fifo->size - 1)), l); ++ ++ /* then get the rest (if any) from the beginning of the buffer */ ++ memcpy(buffer + l, fifo->buffer, len - l); ++ ++ /* ++ * Ensure that we remove the bytes from the kfifo -before- ++ * we update the fifo->out index. ++ */ ++ ++ smp_mb(); ++ ++ fifo->out += len; ++ ++ return len; ++} ++EXPORT_SYMBOL(__kfifo_get); ++ ++#endif +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/linux_resource_internal.h 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,76 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file contains Linux-specific API internal for the resource driver. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * Certain parts of the driver were implemented by ++ * Alexandra Kossovsky ++ * OKTET Labs Ltd, Russia, ++ * http://oktetlabs.ru, ++ * by request of Solarflare Communications ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#ifndef __LINUX_RESOURCE_INTERNAL__ ++#define __LINUX_RESOURCE_INTERNAL__ ++ ++#include ++#include ++#include ++#include ++ ++ ++/*! Linux specific EtherFabric initialisation */ ++extern int ++linux_efrm_nic_ctor(struct linux_efhw_nic *, struct pci_dev *, ++ spinlock_t *reg_lock, ++ unsigned nic_flags, unsigned nic_options); ++ ++/*! Linux specific EtherFabric initialisation */ ++extern void linux_efrm_nic_dtor(struct linux_efhw_nic *); ++ ++/*! Linux specific EtherFabric initialisation -- interrupt registration */ ++extern int linux_efrm_irq_ctor(struct linux_efhw_nic *); ++ ++/*! Linux specific EtherFabric initialisation -- interrupt deregistration */ ++extern void linux_efrm_irq_dtor(struct linux_efhw_nic *); ++ ++extern int efrm_driverlink_register(void); ++extern void efrm_driverlink_unregister(void); ++ ++extern int ++efrm_nic_add(struct pci_dev *dev, unsigned int opts, const uint8_t *mac_addr, ++ struct linux_efhw_nic **lnic_out, spinlock_t *reg_lock, ++ int bt_min, int bt_max, int non_irq_evq, ++ const struct vi_resource_dimensions *); ++extern void efrm_nic_del(struct linux_efhw_nic *); ++ ++ ++extern int efrm_install_proc_entries(void); ++extern void efrm_uninstall_proc_entries(void); ++ ++#endif /* __LINUX_RESOURCE_INTERNAL__ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/nic.c 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,174 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file contains EtherFabric Generic NIC instance (init, interrupts, ++ * etc) ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++ ++int efhw_device_type_init(struct efhw_device_type *dt, ++ int vendor_id, int device_id, ++ int class_revision) ++{ ++ if (vendor_id != 0x1924) ++ return 0; ++ ++ switch (device_id) { ++ case 0x0703: ++ case 0x6703: ++ dt->variant = 'A'; ++ switch (class_revision) { ++ case 0: ++ dt->revision = 0; ++ break; ++ case 1: ++ dt->revision = 1; ++ break; ++ default: ++ return 0; ++ } ++ break; ++ case 0x0710: ++ dt->variant = 'B'; ++ switch (class_revision) { ++ case 2: ++ dt->revision = 0; ++ break; ++ default: ++ return 0; ++ } ++ break; ++ default: ++ return 0; ++ } ++ ++ return 1; ++} ++ ++ ++/*-------------------------------------------------------------------- ++ * ++ * NIC Initialisation ++ * ++ *--------------------------------------------------------------------*/ ++ ++/* make this separate from initialising data structure ++** to allow this to be called at a later time once we can access PCI ++** config space to find out what hardware we have ++*/ ++void efhw_nic_init(struct efhw_nic *nic, unsigned flags, unsigned options, ++ struct efhw_device_type dev_type) ++{ ++ nic->devtype = dev_type; ++ nic->flags = flags; ++ nic->options = options; ++ nic->bar_ioaddr = 0; ++ spin_lock_init(&nic->the_reg_lock); ++ nic->reg_lock = &nic->the_reg_lock; ++ nic->mtu = 1500 + ETH_HLEN; ++ ++ nic->irq_unit = EFHW_IRQ_UNIT_UNUSED; ++ ++ nic->evq_sizes = 512 | 1024 | 2048 | 4096 | 8192 | ++ 16384 | 32768; ++ nic->txq_sizes = 512 | 1024 | 2048 | 4096; ++ nic->rxq_sizes = 512 | 1024 | 2048 | 4096; ++ nic->efhw_func = &falcon_char_functional_units; ++ nic->ctr_ap_bytes = EFHW_64M; ++ switch (nic->devtype.variant) { ++ case 'A': ++ nic->ctr_ap_bar = FALCON_S_CTR_AP_BAR; ++ nic->num_evqs = 4096; ++ nic->num_dmaqs = 4096; ++ nic->num_timers = 4096; ++ break; ++ case 'B': ++ nic->flags |= NIC_FLAG_NO_INTERRUPT; ++ nic->ctr_ap_bar = FALCON_P_CTR_AP_BAR; ++ nic->num_evqs = 4096; ++ nic->num_dmaqs = 4096; ++ nic->num_timers = 4096; ++ break; ++ default: ++ EFHW_ASSERT(0); ++ break; ++ } ++} ++ ++ ++void efhw_nic_close_interrupts(struct efhw_nic *nic) ++{ ++ EFHW_ASSERT(nic); ++ if (!efhw_nic_have_hw(nic)) ++ return; ++ ++ EFHW_ASSERT(efhw_nic_have_hw(nic)); ++ ++ if (nic->irq_unit != EFHW_IRQ_UNIT_UNUSED) ++ efhw_nic_interrupt_disable(nic); ++} ++ ++void efhw_nic_dtor(struct efhw_nic *nic) ++{ ++ EFHW_ASSERT(nic); ++ ++ /* Check that we have functional units because the software only ++ * driver doesn't initialise anything hardware related any more */ ++ ++ /* close interrupts is called first because the act of deregistering ++ the driver could cause this driver to change from master to slave ++ and hence the implicit interrupt mappings would be wrong */ ++ ++ EFHW_TRACE("%s: functional units ... ", __func__); ++ ++ if (efhw_nic_have_functional_units(nic)) { ++ efhw_nic_close_interrupts(nic); ++ efhw_nic_close_hardware(nic); ++ } ++ EFHW_TRACE("%s: functional units ... done", __func__); ++ ++ /* destroy event queues */ ++ EFHW_TRACE("%s: event queues ... ", __func__); ++ ++ if (nic->interrupting_evq.evq_mask) ++ efhw_keventq_dtor(nic, &nic->interrupting_evq); ++ if (nic->non_interrupting_evq.evq_mask) ++ efhw_keventq_dtor(nic, &nic->non_interrupting_evq); ++ ++ EFHW_TRACE("%s: event queues ... done", __func__); ++ ++ spin_lock_destroy(&nic->the_reg_lock); ++ ++ EFHW_TRACE("%s: DONE", __func__); ++} +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/resource_driver.c 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,600 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file contains main driver entry points. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * Certain parts of the driver were implemented by ++ * Alexandra Kossovsky ++ * OKTET Labs Ltd, Russia, ++ * http://oktetlabs.ru, ++ * by request of Solarflare Communications ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#include "linux_resource_internal.h" ++#include "kernel_compat.h" ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++MODULE_AUTHOR("Solarflare Communications"); ++MODULE_LICENSE("GPL"); ++ ++static struct efhw_ev_handler ev_handler = { ++ .wakeup_fn = efrm_handle_wakeup_event, ++ .timeout_fn = efrm_handle_timeout_event, ++ .dmaq_flushed_fn = efrm_handle_dmaq_flushed, ++}; ++ ++const int max_hardware_init_repeats = 10; ++ ++/*-------------------------------------------------------------------- ++ * ++ * Module load time variables ++ * ++ *--------------------------------------------------------------------*/ ++/* See docs/notes/pci_alloc_consistent */ ++static int do_irq = 1; /* enable interrupts */ ++ ++#if defined(CONFIG_X86_XEN) ++static int irq_moderation = 60; /* interrupt moderation (60 usec) */ ++#else ++static int irq_moderation = 20; /* interrupt moderation (20 usec) */ ++#endif ++static int nic_options = NIC_OPT_DEFAULT; ++int efx_vi_eventq_size = EFX_VI_EVENTQ_SIZE_DEFAULT; ++ ++module_param(do_irq, int, S_IRUGO); ++MODULE_PARM_DESC(do_irq, "Enable interrupts. " ++ "Do not turn it off unless you know what are you doing."); ++module_param(irq_moderation, int, S_IRUGO); ++MODULE_PARM_DESC(irq_moderation, "IRQ moderation in usec"); ++module_param(nic_options, int, S_IRUGO); ++MODULE_PARM_DESC(nic_options, "Nic options -- see efhw_types.h"); ++module_param(efx_vi_eventq_size, int, S_IRUGO); ++MODULE_PARM_DESC(efx_vi_eventq_size, ++ "Size of event queue allocated by efx_vi library"); ++ ++/*-------------------------------------------------------------------- ++ * ++ * Linux specific NIC initialisation ++ * ++ *--------------------------------------------------------------------*/ ++ ++static inline irqreturn_t ++linux_efrm_interrupt(int irr, void *dev_id) ++{ ++ return efhw_nic_interrupt((struct efhw_nic *)dev_id); ++} ++ ++int linux_efrm_irq_ctor(struct linux_efhw_nic *lnic) ++{ ++ struct efhw_nic *nic = &lnic->efrm_nic.efhw_nic; ++ ++ nic->flags &= ~NIC_FLAG_MSI; ++ if (nic->flags & NIC_FLAG_TRY_MSI) { ++ int rc = pci_enable_msi(lnic->pci_dev); ++ if (rc < 0) { ++ EFRM_WARN("%s: Could not enable MSI (%d)", ++ __func__, rc); ++ EFRM_WARN("%s: Continuing with legacy interrupt mode", ++ __func__); ++ } else { ++ EFRM_NOTICE("%s: MSI enabled", __func__); ++ nic->flags |= NIC_FLAG_MSI; ++ } ++ } ++ ++ if (request_irq(lnic->pci_dev->irq, linux_efrm_interrupt, ++ IRQF_SHARED, "sfc_resource", nic)) { ++ EFRM_ERR("Request for interrupt #%d failed", ++ lnic->pci_dev->irq); ++ nic->flags &= ~NIC_FLAG_OS_IRQ_EN; ++ return -EBUSY; ++ } ++ nic->flags |= NIC_FLAG_OS_IRQ_EN; ++ ++ return 0; ++} ++ ++void linux_efrm_irq_dtor(struct linux_efhw_nic *lnic) ++{ ++ EFRM_TRACE("%s: start", __func__); ++ ++ if (lnic->efrm_nic.efhw_nic.flags & NIC_FLAG_OS_IRQ_EN) { ++ free_irq(lnic->pci_dev->irq, &lnic->efrm_nic.efhw_nic); ++ lnic->efrm_nic.efhw_nic.flags &= ~NIC_FLAG_OS_IRQ_EN; ++ } ++ ++ if (lnic->efrm_nic.efhw_nic.flags & NIC_FLAG_MSI) { ++ pci_disable_msi(lnic->pci_dev); ++ lnic->efrm_nic.efhw_nic.flags &= ~NIC_FLAG_MSI; ++ } ++ ++ EFRM_TRACE("%s: done", __func__); ++} ++ ++/* Allocate buffer table entries for a particular NIC. ++ */ ++static int efrm_nic_buffer_table_alloc(struct efhw_nic *nic) ++{ ++ int capacity; ++ int page_order; ++ int rc; ++ ++ /* Choose queue size. */ ++ for (capacity = 8192; capacity <= nic->evq_sizes; capacity <<= 1) { ++ if (capacity > nic->evq_sizes) { ++ EFRM_ERR ++ ("%s: Unable to choose EVQ size (supported=%x)", ++ __func__, nic->evq_sizes); ++ return -E2BIG; ++ } else if (capacity & nic->evq_sizes) ++ break; ++ } ++ ++ nic->interrupting_evq.hw.capacity = capacity; ++ nic->interrupting_evq.hw.buf_tbl_alloc.base = (unsigned)-1; ++ ++ nic->non_interrupting_evq.hw.capacity = capacity; ++ nic->non_interrupting_evq.hw.buf_tbl_alloc.base = (unsigned)-1; ++ ++ /* allocate buffer table entries to map onto the iobuffer */ ++ page_order = get_order(capacity * sizeof(efhw_event_t)); ++ if (!(nic->flags & NIC_FLAG_NO_INTERRUPT)) { ++ rc = efrm_buffer_table_alloc(page_order, ++ &nic->interrupting_evq ++ .hw.buf_tbl_alloc); ++ if (rc < 0) { ++ EFRM_WARN ++ ("%s: failed (%d) to alloc %d buffer table entries", ++ __func__, rc, page_order); ++ return rc; ++ } ++ } ++ rc = efrm_buffer_table_alloc(page_order, ++ &nic->non_interrupting_evq.hw. ++ buf_tbl_alloc); ++ if (rc < 0) { ++ EFRM_WARN ++ ("%s: failed (%d) to alloc %d buffer table entries", ++ __func__, rc, page_order); ++ return rc; ++ } ++ ++ return 0; ++} ++ ++/* Free buffer table entries allocated for a particular NIC. ++ */ ++static void efrm_nic_buffer_table_free(struct efhw_nic *nic) ++{ ++ if (nic->interrupting_evq.hw.buf_tbl_alloc.base != (unsigned)-1) ++ efrm_buffer_table_free(&nic->interrupting_evq.hw ++ .buf_tbl_alloc); ++ if (nic->non_interrupting_evq.hw.buf_tbl_alloc.base != (unsigned)-1) ++ efrm_buffer_table_free(&nic->non_interrupting_evq ++ .hw.buf_tbl_alloc); ++} ++ ++static int iomap_bar(struct linux_efhw_nic *lnic, size_t len) ++{ ++ volatile char __iomem *ioaddr; ++ ++ ioaddr = ioremap_nocache(lnic->ctr_ap_pci_addr, len); ++ if (ioaddr == 0) ++ return -ENOMEM; ++ ++ lnic->efrm_nic.efhw_nic.bar_ioaddr = ioaddr; ++ return 0; ++} ++ ++static int linux_efhw_nic_map_ctr_ap(struct linux_efhw_nic *lnic) ++{ ++ struct efhw_nic *nic = &lnic->efrm_nic.efhw_nic; ++ int rc; ++ ++ rc = iomap_bar(lnic, nic->ctr_ap_bytes); ++ ++ /* Bug 5195: workaround for now. */ ++ if (rc != 0 && nic->ctr_ap_bytes > 16 * 1024 * 1024) { ++ /* Try half the size for now. */ ++ nic->ctr_ap_bytes /= 2; ++ EFRM_WARN("Bug 5195 WORKAROUND: retrying iomap of %d bytes", ++ nic->ctr_ap_bytes); ++ rc = iomap_bar(lnic, nic->ctr_ap_bytes); ++ } ++ ++ if (rc < 0) { ++ EFRM_ERR("Failed (%d) to map bar (%d bytes)", ++ rc, nic->ctr_ap_bytes); ++ return rc; ++ } ++ ++ return rc; ++} ++ ++int ++linux_efrm_nic_ctor(struct linux_efhw_nic *lnic, struct pci_dev *dev, ++ spinlock_t *reg_lock, ++ unsigned nic_flags, unsigned nic_options) ++{ ++ struct efhw_device_type dev_type; ++ struct efhw_nic *nic = &lnic->efrm_nic.efhw_nic; ++ u8 class_revision; ++ int rc; ++ ++ rc = pci_read_config_byte(dev, PCI_CLASS_REVISION, &class_revision); ++ if (rc != 0) { ++ EFRM_ERR("%s: pci_read_config_byte failed (%d)", ++ __func__, rc); ++ return rc; ++ } ++ ++ if (!efhw_device_type_init(&dev_type, dev->vendor, dev->device, ++ class_revision)) { ++ EFRM_ERR("%s: efhw_device_type_init failed %04x:%04x(%d)", ++ __func__, (unsigned) dev->vendor, ++ (unsigned) dev->device, (int) class_revision); ++ return -ENODEV; ++ } ++ ++ EFRM_NOTICE("attaching device type %04x:%04x %d:%c%d", ++ (unsigned) dev->vendor, (unsigned) dev->device, ++ dev_type.arch, dev_type.variant, dev_type.revision); ++ ++ /* Initialise the adapter-structure. */ ++ efhw_nic_init(nic, nic_flags, nic_options, dev_type); ++ lnic->pci_dev = dev; ++ ++ rc = pci_enable_device(dev); ++ if (rc < 0) { ++ EFRM_ERR("%s: pci_enable_device failed (%d)", ++ __func__, rc); ++ return rc; ++ } ++ ++ lnic->ctr_ap_pci_addr = pci_resource_start(dev, nic->ctr_ap_bar); ++ ++ if (!pci_dma_supported(dev, (dma_addr_t)EFHW_DMA_ADDRMASK)) { ++ EFRM_ERR("%s: pci_dma_supported(%lx) failed", __func__, ++ (unsigned long)EFHW_DMA_ADDRMASK); ++ return -ENODEV; ++ } ++ ++ if (pci_set_dma_mask(dev, (dma_addr_t)EFHW_DMA_ADDRMASK)) { ++ EFRM_ERR("%s: pci_set_dma_mask(%lx) failed", __func__, ++ (unsigned long)EFHW_DMA_ADDRMASK); ++ return -ENODEV; ++ } ++ ++ if (pci_set_consistent_dma_mask(dev, (dma_addr_t)EFHW_DMA_ADDRMASK)) { ++ EFRM_ERR("%s: pci_set_consistent_dma_mask(%lx) failed", ++ __func__, (unsigned long)EFHW_DMA_ADDRMASK); ++ return -ENODEV; ++ } ++ ++ rc = linux_efhw_nic_map_ctr_ap(lnic); ++ if (rc < 0) ++ return rc; ++ ++ /* By default struct efhw_nic contains its own lock for protecting ++ * access to nic registers. We override it with a pointer to the ++ * lock in the net driver. This is needed when resource and net ++ * drivers share a single PCI function (falcon B series). ++ */ ++ nic->reg_lock = reg_lock; ++ return 0; ++} ++ ++void linux_efrm_nic_dtor(struct linux_efhw_nic *lnic) ++{ ++ struct efhw_nic *nic = &lnic->efrm_nic.efhw_nic; ++ volatile char __iomem *bar_ioaddr = nic->bar_ioaddr; ++ ++ efhw_nic_dtor(nic); ++ ++ /* Unmap the bar. */ ++ EFRM_ASSERT(bar_ioaddr); ++ iounmap(bar_ioaddr); ++ nic->bar_ioaddr = 0; ++} ++ ++/**************************************************************************** ++ * ++ * efrm_tasklet - used to poll the eventq which may result in further callbacks ++ * ++ ****************************************************************************/ ++ ++static void efrm_tasklet(unsigned long pdev) ++{ ++ struct efhw_nic *nic = (struct efhw_nic *)pdev; ++ ++ EFRM_ASSERT(!(nic->flags & NIC_FLAG_NO_INTERRUPT)); ++ ++ efhw_keventq_poll(nic, &nic->interrupting_evq); ++ EFRM_TRACE("%s: complete", __func__); ++} ++ ++/**************************************************************************** ++ * ++ * char driver specific interrupt callbacks -- run at hard IRQL ++ * ++ ****************************************************************************/ ++static void efrm_handle_eventq_irq(struct efhw_nic *nic, int evq) ++{ ++ /* NB. The interrupt must have already been acked (for legacy mode). */ ++ ++ EFRM_TRACE("%s: starting tasklet", __func__); ++ EFRM_ASSERT(!(nic->flags & NIC_FLAG_NO_INTERRUPT)); ++ ++ tasklet_schedule(&linux_efhw_nic(nic)->tasklet); ++} ++ ++/* A count of how many NICs this driver knows about. */ ++static int n_nics_probed; ++ ++/**************************************************************************** ++ * ++ * efrm_nic_add: add the NIC to the resource driver ++ * ++ * NOTE: the flow of control through this routine is quite subtle ++ * because of the number of operations that can fail. We therefore ++ * take the apporaching of keeping the return code (rc) variable ++ * accurate, and only do operations while it is non-negative. Tear down ++ * is done at the end if rc is negative, depending on what has been set up ++ * by that point. ++ * ++ * So basically just make sure that any code you add checks rc>=0 before ++ * doing any work and you'll be fine. ++ * ++ ****************************************************************************/ ++int ++efrm_nic_add(struct pci_dev *dev, unsigned flags, const uint8_t *mac_addr, ++ struct linux_efhw_nic **lnic_out, spinlock_t *reg_lock, ++ int bt_min, int bt_lim, int non_irq_evq, ++ const struct vi_resource_dimensions *res_dim) ++{ ++ struct linux_efhw_nic *lnic = NULL; ++ struct efhw_nic *nic = NULL; ++ int count = 0, rc = 0, resources_init = 0; ++ int constructed = 0; ++ int registered_nic = 0; ++ int buffers_allocated = 0; ++ static unsigned nic_index; /* = 0; */ ++ ++ EFRM_TRACE("%s: device detected (Slot '%s', IRQ %d)", __func__, ++ pci_name(dev) ? pci_name(dev) : "?", dev->irq); ++ ++ /* Ensure that we have room for the new adapter-structure. */ ++ if (efrm_nic_tablep->nic_count == EFHW_MAX_NR_DEVS) { ++ EFRM_WARN("%s: WARNING: too many devices", __func__); ++ rc = -ENOMEM; ++ goto failed; ++ } ++ ++ if (n_nics_probed == 0) { ++ rc = efrm_resources_init(res_dim, bt_min, bt_lim); ++ if (rc != 0) ++ goto failed; ++ resources_init = 1; ++ } ++ ++ /* Allocate memory for the new adapter-structure. */ ++ lnic = kmalloc(sizeof(*lnic), GFP_KERNEL); ++ if (lnic == NULL) { ++ EFRM_ERR("%s: ERROR: failed to allocate memory", __func__); ++ rc = -ENOMEM; ++ goto failed; ++ } ++ memset(lnic, 0, sizeof(*lnic)); ++ nic = &lnic->efrm_nic.efhw_nic; ++ ++ lnic->ev_handlers = &ev_handler; ++ ++ /* OS specific hardware mappings */ ++ rc = linux_efrm_nic_ctor(lnic, dev, reg_lock, flags, nic_options); ++ if (rc < 0) { ++ EFRM_ERR("%s: ERROR: initialisation failed", __func__); ++ goto failed; ++ } ++ ++ constructed = 1; ++ ++ /* Tell the driver about the NIC - this needs to be done before the ++ resources managers get created below. Note we haven't initialised ++ the hardware yet, and I don't like doing this before the perhaps ++ unreliable hardware initialisation. However, there's quite a lot ++ of code to review if we wanted to hardware init before bringing ++ up the resource managers. */ ++ rc = efrm_driver_register_nic(&lnic->efrm_nic, nic_index, ++ /* TODO: ifindex */ nic_index); ++ if (rc < 0) { ++ EFRM_ERR("%s: cannot register nic %d with nic error code %d", ++ __func__, efrm_nic_tablep->nic_count, rc); ++ goto failed; ++ } ++ ++nic_index; ++ registered_nic = 1; ++ ++ rc = efrm_nic_buffer_table_alloc(nic); ++ if (rc < 0) ++ goto failed; ++ buffers_allocated = 1; ++ ++ /****************************************************/ ++ /* hardware bringup */ ++ /****************************************************/ ++ /* Detecting hardware can be a slightly unreliable process; ++ we want to make sure that we maximise our chances, so we ++ loop a few times until all is good. */ ++ for (count = 0; count < max_hardware_init_repeats; count++) { ++ rc = efhw_nic_init_hardware(nic, &ev_handler, mac_addr, ++ non_irq_evq); ++ if (rc >= 0) ++ break; ++ ++ /* pain */ ++ EFRM_ERR ++ ("error - hardware initialisation failed code %d, " ++ "attempt %d of %d", rc, count + 1, ++ max_hardware_init_repeats); ++ } ++ if (rc < 0) ++ goto failed; ++ ++ tasklet_init(&lnic->tasklet, efrm_tasklet, (ulong)nic); ++ ++ /* set up interrupt handlers (hard-irq) */ ++ nic->irq_handler = &efrm_handle_eventq_irq; ++ ++ /* this device can now take management interrupts */ ++ if (do_irq && !(nic->flags & NIC_FLAG_NO_INTERRUPT)) { ++ rc = linux_efrm_irq_ctor(lnic); ++ if (rc < 0) { ++ EFRM_ERR("Interrupt initialisation failed (%d)", rc); ++ goto failed; ++ } ++ efhw_nic_set_interrupt_moderation(nic, -1, irq_moderation); ++ efhw_nic_interrupt_enable(nic); ++ } ++ EFRM_TRACE("interrupts are %sregistered", do_irq ? "" : "not "); ++ ++ *lnic_out = lnic; ++ EFRM_ASSERT(rc == 0); ++ ++n_nics_probed; ++ return 0; ++ ++failed: ++ if (buffers_allocated) ++ efrm_nic_buffer_table_free(nic); ++ if (registered_nic) ++ efrm_driver_unregister_nic(&lnic->efrm_nic); ++ if (constructed) ++ linux_efrm_nic_dtor(lnic); ++ kfree(lnic); /* safe in any case */ ++ if (resources_init) ++ efrm_resources_fini(); ++ return rc; ++} ++ ++/**************************************************************************** ++ * ++ * efrm_nic_del: Remove the nic from the resource driver structures ++ * ++ ****************************************************************************/ ++void efrm_nic_del(struct linux_efhw_nic *lnic) ++{ ++ struct efhw_nic *nic = &lnic->efrm_nic.efhw_nic; ++ ++ EFRM_TRACE("%s:", __func__); ++ EFRM_ASSERT(nic); ++ ++ efrm_nic_buffer_table_free(nic); ++ ++ efrm_driver_unregister_nic(&lnic->efrm_nic); ++ ++ /* ++ * Synchronise here with any running ISR. ++ * Remove the OS handler. There should be no IRQs being generated ++ * by our NIC at this point. ++ */ ++ if (efhw_nic_have_functional_units(nic)) { ++ efhw_nic_close_interrupts(nic); ++ linux_efrm_irq_dtor(lnic); ++ tasklet_kill(&lnic->tasklet); ++ } ++ ++ /* Close down hardware and free resources. */ ++ linux_efrm_nic_dtor(lnic); ++ kfree(lnic); ++ ++ if (--n_nics_probed == 0) ++ efrm_resources_fini(); ++ ++ EFRM_TRACE("%s: done", __func__); ++} ++ ++/**************************************************************************** ++ * ++ * init_module: register as a PCI driver. ++ * ++ ****************************************************************************/ ++static int init_sfc_resource(void) ++{ ++ int rc = 0; ++ ++ EFRM_TRACE("%s: RESOURCE driver starting", __func__); ++ ++ efrm_driver_ctor(); ++ ++ /* Register the driver so that our 'probe' function is called for ++ * each EtherFabric device in the system. ++ */ ++ rc = efrm_driverlink_register(); ++ if (rc == -ENODEV) ++ EFRM_ERR("%s: no devices found", __func__); ++ if (rc < 0) ++ goto failed_driverlink; ++ ++ if (efrm_install_proc_entries() != 0) { ++ /* Do not fail, but print a warning */ ++ EFRM_WARN("%s: WARNING: failed to install /proc entries", ++ __func__); ++ } ++ ++ return 0; ++ ++failed_driverlink: ++ efrm_driver_dtor(); ++ return rc; ++} ++ ++/**************************************************************************** ++ * ++ * cleanup_module: module-removal entry-point ++ * ++ ****************************************************************************/ ++static void cleanup_sfc_resource(void) ++{ ++ efrm_uninstall_proc_entries(); ++ ++ efrm_driverlink_unregister(); ++ ++ /* Clean up char-driver specific initialisation. ++ - driver dtor can use both work queue and buffer table entries */ ++ efrm_driver_dtor(); ++ ++ EFRM_TRACE("%s: unloaded", __func__); ++} ++ ++module_init(init_sfc_resource); ++module_exit(cleanup_sfc_resource); +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/resource_manager.c 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,145 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file contains generic code for resources and resource managers. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * Certain parts of the driver were implemented by ++ * Alexandra Kossovsky ++ * OKTET Labs Ltd, Russia, ++ * http://oktetlabs.ru, ++ * by request of Solarflare Communications ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include "efrm_internal.h" ++ ++/********************************************************************** ++ * struct efrm_resource_manager ++ */ ++ ++void efrm_resource_manager_dtor(struct efrm_resource_manager *rm) ++{ ++ EFRM_RESOURCE_MANAGER_ASSERT_VALID(rm); ++ ++ /* call destructor */ ++ EFRM_DO_DEBUG(if (rm->rm_resources) ++ EFRM_ERR("%s: %s leaked %d resources", ++ __func__, rm->rm_name, rm->rm_resources)); ++ EFRM_ASSERT(rm->rm_resources == 0); ++ EFRM_ASSERT(list_empty(&rm->rm_resources_list)); ++ ++ rm->rm_dtor(rm); ++ ++ /* clear out things built by efrm_resource_manager_ctor */ ++ spin_lock_destroy(&rm->rm_lock); ++ ++ /* and the free the memory */ ++ EFRM_DO_DEBUG(memset(rm, 0, sizeof(*rm))); ++ kfree(rm); ++} ++ ++/* Construct a resource manager. Resource managers are singletons. */ ++int ++efrm_resource_manager_ctor(struct efrm_resource_manager *rm, ++ void (*dtor)(struct efrm_resource_manager *), ++ const char *name, unsigned type) ++{ ++ EFRM_ASSERT(rm); ++ EFRM_ASSERT(dtor); ++ ++ rm->rm_name = name; ++ EFRM_DO_DEBUG(rm->rm_type = type); ++ rm->rm_dtor = dtor; ++ spin_lock_init(&rm->rm_lock); ++ rm->rm_resources = 0; ++ rm->rm_resources_hiwat = 0; ++ INIT_LIST_HEAD(&rm->rm_resources_list); ++ EFRM_RESOURCE_MANAGER_ASSERT_VALID(rm); ++ return 0; ++} ++ ++ ++void efrm_client_add_resource(struct efrm_client *client, ++ struct efrm_resource *rs) ++{ ++ struct efrm_resource_manager *rm; ++ irq_flags_t lock_flags; ++ ++ EFRM_ASSERT(client != NULL); ++ EFRM_ASSERT(rs != NULL); ++ ++ spin_lock_irqsave(&efrm_nic_tablep->lock, lock_flags); ++ rm = efrm_rm_table[EFRM_RESOURCE_TYPE(rs->rs_handle)]; ++ ++rm->rm_resources; ++ list_add(&rs->rs_manager_link, &rm->rm_resources_list); ++ if (rm->rm_resources > rm->rm_resources_hiwat) ++ rm->rm_resources_hiwat = rm->rm_resources; ++ rs->rs_client = client; ++ ++client->ref_count; ++ list_add(&rs->rs_client_link, &client->resources); ++ spin_unlock_irqrestore(&efrm_nic_tablep->lock, lock_flags); ++} ++ ++ ++void efrm_resource_ref(struct efrm_resource *rs) ++{ ++ irq_flags_t lock_flags; ++ spin_lock_irqsave(&efrm_nic_tablep->lock, lock_flags); ++ ++rs->rs_ref_count; ++ spin_unlock_irqrestore(&efrm_nic_tablep->lock, lock_flags); ++} ++EXPORT_SYMBOL(efrm_resource_ref); ++ ++ ++int __efrm_resource_release(struct efrm_resource *rs) ++{ ++ struct efrm_resource_manager *rm; ++ irq_flags_t lock_flags; ++ int free_rs; ++ ++ spin_lock_irqsave(&efrm_nic_tablep->lock, lock_flags); ++ free_rs = --rs->rs_ref_count == 0; ++ if (free_rs) { ++ rm = efrm_rm_table[EFRM_RESOURCE_TYPE(rs->rs_handle)]; ++ EFRM_ASSERT(rm->rm_resources > 0); ++ --rm->rm_resources; ++ list_del(&rs->rs_manager_link); ++ list_del(&rs->rs_client_link); ++ } ++ spin_unlock_irqrestore(&efrm_nic_tablep->lock, lock_flags); ++ return free_rs; ++} ++EXPORT_SYMBOL(__efrm_resource_release); ++ ++/* ++ * vi: sw=8:ai:aw ++ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/resources.c 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,94 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file contains resource managers initialisation functions. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * Certain parts of the driver were implemented by ++ * Alexandra Kossovsky ++ * OKTET Labs Ltd, Russia, ++ * http://oktetlabs.ru, ++ * by request of Solarflare Communications ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#include ++#include ++ ++int ++efrm_resources_init(const struct vi_resource_dimensions *vi_res_dim, ++ int buffer_table_min, int buffer_table_lim) ++{ ++ int i, rc; ++ ++ rc = efrm_buffer_table_ctor(buffer_table_min, buffer_table_lim); ++ if (rc != 0) ++ return rc; ++ ++ /* Create resources in the correct order */ ++ for (i = 0; i < EFRM_RESOURCE_NUM; ++i) { ++ struct efrm_resource_manager **rmp = &efrm_rm_table[i]; ++ ++ EFRM_ASSERT(*rmp == NULL); ++ switch (i) { ++ case EFRM_RESOURCE_VI: ++ rc = efrm_create_vi_resource_manager(rmp, ++ vi_res_dim); ++ break; ++ case EFRM_RESOURCE_FILTER: ++ rc = efrm_create_filter_resource_manager(rmp); ++ break; ++ case EFRM_RESOURCE_IOBUFSET: ++ rc = efrm_create_iobufset_resource_manager(rmp); ++ break; ++ default: ++ rc = 0; ++ break; ++ } ++ ++ if (rc < 0) { ++ EFRM_ERR("%s: failed type=%d (%d)", ++ __func__, i, rc); ++ efrm_buffer_table_dtor(); ++ return rc; ++ } ++ } ++ ++ return 0; ++} ++ ++void efrm_resources_fini(void) ++{ ++ int i; ++ ++ for (i = EFRM_RESOURCE_NUM - 1; i >= 0; --i) ++ if (efrm_rm_table[i]) { ++ efrm_resource_manager_dtor(efrm_rm_table[i]); ++ efrm_rm_table[i] = NULL; ++ } ++ ++ efrm_buffer_table_dtor(); ++} +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/vi_resource_alloc.c 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,820 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file contains allocation of VI resources. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * Certain parts of the driver were implemented by ++ * Alexandra Kossovsky ++ * OKTET Labs Ltd, Russia, ++ * http://oktetlabs.ru, ++ * by request of Solarflare Communications ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "efrm_internal.h" ++ ++ ++/*** Data definitions ****************************************************/ ++ ++static const char *dmaq_names[] = { "TX", "RX" }; ++ ++struct vi_resource_manager *efrm_vi_manager; ++ ++/*** Forward references **************************************************/ ++ ++static int ++efrm_vi_resource_alloc_or_free(struct efrm_client *client, ++ int alloc, struct vi_resource *evq_virs, ++ uint16_t vi_flags, int32_t evq_capacity, ++ int32_t txq_capacity, int32_t rxq_capacity, ++ uint8_t tx_q_tag, uint8_t rx_q_tag, ++ struct vi_resource **virs_in_out); ++ ++/*** Reference count handling ********************************************/ ++ ++static inline void efrm_vi_rm_get_ref(struct vi_resource *virs) ++{ ++ atomic_inc(&virs->evq_refs); ++} ++ ++static inline void efrm_vi_rm_drop_ref(struct vi_resource *virs) ++{ ++ EFRM_ASSERT(atomic_read(&virs->evq_refs) != 0); ++ if (atomic_dec_and_test(&virs->evq_refs)) ++ efrm_vi_resource_alloc_or_free(virs->rs.rs_client, false, NULL, ++ 0, 0, 0, 0, 0, 0, &virs); ++} ++ ++/*** Instance numbers ****************************************************/ ++ ++static inline int efrm_vi_rm_alloc_id(uint16_t vi_flags, int32_t evq_capacity) ++{ ++ irq_flags_t lock_flags; ++ int instance; ++ int rc; ++ ++ if (efrm_nic_tablep->a_nic == NULL) /* ?? FIXME: surely not right */ ++ return -ENODEV; ++ ++ spin_lock_irqsave(&efrm_vi_manager->rm.rm_lock, lock_flags); ++ ++ /* Falcon A1 RX phys addr wierdness. */ ++ if (efrm_nic_tablep->a_nic->devtype.variant == 'A' && ++ (vi_flags & EFHW_VI_RX_PHYS_ADDR_EN)) { ++ if (vi_flags & EFHW_VI_JUMBO_EN) { ++ /* Falcon-A cannot do phys + scatter. */ ++ EFRM_WARN ++ ("%s: falcon-A does not support phys+scatter mode", ++ __func__); ++ instance = -1; ++ } else if (efrm_vi_manager->iscsi_dmaq_instance_is_free ++ && evq_capacity == 0) { ++ /* Falcon-A has a single RXQ that gives the correct ++ * semantics for physical addressing. However, it ++ * happens to have the same instance number as the ++ * 'char' event queue, so we cannot also hand out ++ * the event queue. */ ++ efrm_vi_manager->iscsi_dmaq_instance_is_free = false; ++ instance = FALCON_A1_ISCSI_DMAQ; ++ } else { ++ EFRM_WARN("%s: iSCSI receive queue not free", ++ __func__); ++ instance = -1; ++ } ++ goto unlock_out; ++ } ++ ++ if (vi_flags & EFHW_VI_RM_WITH_INTERRUPT) { ++ rc = __kfifo_get(efrm_vi_manager->instances_with_interrupt, ++ (unsigned char *)&instance, sizeof(instance)); ++ if (rc != sizeof(instance)) { ++ EFRM_ASSERT(rc == 0); ++ instance = -1; ++ } ++ goto unlock_out; ++ } ++ ++ /* Otherwise a normal run-of-the-mill VI. */ ++ rc = __kfifo_get(efrm_vi_manager->instances_with_timer, ++ (unsigned char *)&instance, sizeof(instance)); ++ if (rc != sizeof(instance)) { ++ EFRM_ASSERT(rc == 0); ++ instance = -1; ++ } ++ ++unlock_out: ++ spin_unlock_irqrestore(&efrm_vi_manager->rm.rm_lock, lock_flags); ++ return instance; ++} ++ ++static void efrm_vi_rm_free_id(int instance) ++{ ++ irq_flags_t lock_flags; ++ struct kfifo *instances; ++ ++ if (efrm_nic_tablep->a_nic == NULL) /* ?? FIXME: surely not right */ ++ return; ++ ++ if (efrm_nic_tablep->a_nic->devtype.variant == 'A' && ++ instance == FALCON_A1_ISCSI_DMAQ) { ++ EFRM_ASSERT(efrm_vi_manager->iscsi_dmaq_instance_is_free == ++ false); ++ spin_lock_irqsave(&efrm_vi_manager->rm.rm_lock, lock_flags); ++ efrm_vi_manager->iscsi_dmaq_instance_is_free = true; ++ spin_unlock_irqrestore(&efrm_vi_manager->rm.rm_lock, ++ lock_flags); ++ } else { ++ if (instance >= efrm_vi_manager->with_timer_base && ++ instance < efrm_vi_manager->with_timer_limit) { ++ instances = efrm_vi_manager->instances_with_timer; ++ } else { ++ EFRM_ASSERT(instance >= ++ efrm_vi_manager->with_interrupt_base); ++ EFRM_ASSERT(instance < ++ efrm_vi_manager->with_interrupt_limit); ++ instances = efrm_vi_manager->instances_with_interrupt; ++ } ++ ++ EFRM_VERIFY_EQ(kfifo_put(instances, (unsigned char *)&instance, ++ sizeof(instance)), sizeof(instance)); ++ } ++} ++ ++/*** Queue sizes *********************************************************/ ++ ++/* NB. This should really take a nic as an argument, but that makes ++ * the buffer table allocation difficult. */ ++uint32_t efrm_vi_rm_evq_bytes(struct vi_resource *virs ++ /*,struct efhw_nic *nic */) ++{ ++ return virs->evq_capacity * sizeof(efhw_event_t); ++} ++EXPORT_SYMBOL(efrm_vi_rm_evq_bytes); ++ ++/* NB. This should really take a nic as an argument, but that makes ++ * the buffer table allocation difficult. */ ++uint32_t efrm_vi_rm_txq_bytes(struct vi_resource *virs ++ /*,struct efhw_nic *nic */) ++{ ++ return virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_TX] * ++ FALCON_DMA_TX_DESC_BYTES; ++} ++EXPORT_SYMBOL(efrm_vi_rm_txq_bytes); ++ ++/* NB. This should really take a nic as an argument, but that makes ++ * the buffer table allocation difficult. */ ++uint32_t efrm_vi_rm_rxq_bytes(struct vi_resource *virs ++ /*,struct efhw_nic *nic */) ++{ ++ uint32_t bytes_per_desc = ((virs->flags & EFHW_VI_RX_PHYS_ADDR_EN) ++ ? FALCON_DMA_RX_PHYS_DESC_BYTES ++ : FALCON_DMA_RX_BUF_DESC_BYTES); ++ return virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_RX] * bytes_per_desc; ++} ++EXPORT_SYMBOL(efrm_vi_rm_rxq_bytes); ++ ++static int choose_size(int size_rq, unsigned sizes) ++{ ++ int size; ++ ++ /* size_rq < 0 means default, but we interpret this as 'minimum'. */ ++ ++ for (size = 256;; size <<= 1) ++ if ((size & sizes) && size >= size_rq) ++ return size; ++ else if ((sizes & ~((size - 1) | size)) == 0) ++ return -1; ++} ++ ++static int ++efrm_vi_rm_adjust_alloc_request(struct vi_resource *virs, struct efhw_nic *nic) ++{ ++ int capacity; ++ ++ EFRM_ASSERT(nic->efhw_func); ++ ++ if (virs->evq_capacity) { ++ capacity = choose_size(virs->evq_capacity, nic->evq_sizes); ++ if (capacity < 0) { ++ EFRM_ERR("vi_resource: bad evq size %d (supported=%x)", ++ virs->evq_capacity, nic->evq_sizes); ++ return -E2BIG; ++ } ++ virs->evq_capacity = capacity; ++ } ++ if (virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_TX]) { ++ capacity = ++ choose_size(virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_TX], ++ nic->txq_sizes); ++ if (capacity < 0) { ++ EFRM_ERR("vi_resource: bad txq size %d (supported=%x)", ++ virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_TX], ++ nic->txq_sizes); ++ return -E2BIG; ++ } ++ virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_TX] = capacity; ++ } ++ if (virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_RX]) { ++ capacity = ++ choose_size(virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_RX], ++ nic->rxq_sizes); ++ if (capacity < 0) { ++ EFRM_ERR("vi_resource: bad rxq size %d (supported=%x)", ++ virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_RX], ++ nic->rxq_sizes); ++ return -E2BIG; ++ } ++ virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_RX] = capacity; ++ } ++ ++ return 0; ++} ++ ++/* remove the reference to the event queue in this VI resource and decrement ++ the event queue's use count */ ++static inline void efrm_vi_rm_detach_evq(struct vi_resource *virs) ++{ ++ struct vi_resource *evq_virs; ++ ++ EFRM_ASSERT(virs != NULL); ++ ++ evq_virs = virs->evq_virs; ++ ++ if (evq_virs != NULL) { ++ virs->evq_virs = NULL; ++ if (evq_virs == virs) { ++ EFRM_TRACE("%s: " EFRM_RESOURCE_FMT ++ " had internal event queue ", __func__, ++ EFRM_RESOURCE_PRI_ARG(virs->rs.rs_handle)); ++ } else { ++ efrm_vi_rm_drop_ref(evq_virs); ++ EFRM_TRACE("%s: " EFRM_RESOURCE_FMT " had event queue " ++ EFRM_RESOURCE_FMT, __func__, ++ EFRM_RESOURCE_PRI_ARG(virs->rs.rs_handle), ++ EFRM_RESOURCE_PRI_ARG(evq_virs->rs. ++ rs_handle)); ++ } ++ } else { ++ EFRM_TRACE("%s: " EFRM_RESOURCE_FMT ++ " had no event queue (nothing to do)", ++ __func__, ++ EFRM_RESOURCE_PRI_ARG(virs->rs.rs_handle)); ++ } ++} ++ ++/*** Buffer Table allocations ********************************************/ ++ ++static int ++efrm_vi_rm_alloc_or_free_buffer_table(struct vi_resource *virs, bool is_alloc) ++{ ++ uint32_t bytes; ++ int page_order; ++ int rc; ++ ++ if (!is_alloc) ++ goto destroy; ++ ++ if (virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_TX]) { ++ bytes = efrm_vi_rm_txq_bytes(virs); ++ page_order = get_order(bytes); ++ rc = efrm_buffer_table_alloc(page_order, ++ (virs->dmaq_buf_tbl_alloc + ++ EFRM_VI_RM_DMA_QUEUE_TX)); ++ if (rc != 0) { ++ EFRM_TRACE ++ ("%s: Error %d allocating TX buffer table entry", ++ __func__, rc); ++ goto fail_txq_alloc; ++ } ++ } ++ ++ if (virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_RX]) { ++ bytes = efrm_vi_rm_rxq_bytes(virs); ++ page_order = get_order(bytes); ++ rc = efrm_buffer_table_alloc(page_order, ++ (virs->dmaq_buf_tbl_alloc + ++ EFRM_VI_RM_DMA_QUEUE_RX)); ++ if (rc != 0) { ++ EFRM_TRACE ++ ("%s: Error %d allocating RX buffer table entry", ++ __func__, rc); ++ goto fail_rxq_alloc; ++ } ++ } ++ return 0; ++ ++destroy: ++ rc = 0; ++ ++ if (virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_RX]) { ++ efrm_buffer_table_free(&virs-> ++ dmaq_buf_tbl_alloc ++ [EFRM_VI_RM_DMA_QUEUE_RX]); ++ } ++fail_rxq_alloc: ++ ++ if (virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_TX]) { ++ efrm_buffer_table_free(&virs-> ++ dmaq_buf_tbl_alloc ++ [EFRM_VI_RM_DMA_QUEUE_TX]); ++ } ++fail_txq_alloc: ++ ++ return rc; ++} ++ ++/*** Per-NIC allocations *************************************************/ ++ ++static inline int ++efrm_vi_rm_init_evq(struct vi_resource *virs, struct efhw_nic *nic) ++{ ++ int instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle); ++ struct eventq_resource_hardware *evq_hw = ++ &virs->nic_info.evq_pages; ++ uint32_t buf_bytes = efrm_vi_rm_evq_bytes(virs); ++ int rc; ++ ++ if (virs->evq_capacity == 0) ++ return 0; ++ evq_hw->capacity = virs->evq_capacity; ++ ++ /* Allocate buffer table entries to map onto the iobuffer. This ++ * currently allocates its own buffer table entries on Falcon which is ++ * a bit wasteful on a multi-NIC system. */ ++ evq_hw->buf_tbl_alloc.base = (unsigned)-1; ++ rc = efrm_buffer_table_alloc(get_order(buf_bytes), ++ &evq_hw->buf_tbl_alloc); ++ if (rc < 0) { ++ EFHW_WARN("%s: failed (%d) to alloc %d buffer table entries", ++ __func__, rc, get_order(buf_bytes)); ++ return rc; ++ } ++ ++ /* Allocate the event queue memory. */ ++ rc = efhw_nic_event_queue_alloc_iobuffer(nic, evq_hw, instance, ++ buf_bytes); ++ if (rc != 0) { ++ EFRM_ERR("%s: Error allocating iobuffer: %d", __func__, rc); ++ efrm_buffer_table_free(&evq_hw->buf_tbl_alloc); ++ return rc; ++ } ++ ++ /* Initialise the event queue hardware */ ++ efhw_nic_event_queue_enable(nic, instance, virs->evq_capacity, ++ efhw_iopages_dma_addr(&evq_hw->iobuff) + ++ evq_hw->iobuff_off, ++ evq_hw->buf_tbl_alloc.base, ++ instance < 64); ++ ++ EFRM_TRACE("%s: " EFRM_RESOURCE_FMT " capacity=%u", __func__, ++ EFRM_RESOURCE_PRI_ARG(virs->rs.rs_handle), ++ virs->evq_capacity); ++ ++#if defined(__ia64__) ++ /* Page size may be large, so for now just increase the ++ * size of the requested evq up to a round number of ++ * pages ++ */ ++ buf_bytes = CI_ROUNDUP(buf_bytes, PAGE_SIZE); ++#endif ++ EFRM_ASSERT(buf_bytes % PAGE_SIZE == 0); ++ ++ virs->mem_mmap_bytes += buf_bytes; ++ ++ return 0; ++} ++ ++static inline void ++efrm_vi_rm_fini_evq(struct vi_resource *virs, struct efhw_nic *nic) ++{ ++ int instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle); ++ struct vi_resource_nic_info *nic_info = &virs->nic_info; ++ ++ if (virs->evq_capacity == 0) ++ return; ++ ++ /* Zero the timer-value for this queue. ++ And Tell NIC to stop using this event queue. */ ++ efhw_nic_event_queue_disable(nic, instance, 0); ++ ++ if (nic_info->evq_pages.buf_tbl_alloc.base != (unsigned)-1) ++ efrm_buffer_table_free(&nic_info->evq_pages.buf_tbl_alloc); ++ ++ efhw_iopages_free(nic, &nic_info->evq_pages.iobuff); ++} ++ ++/*! FIXME: we should make sure this number is never zero (=> unprotected) */ ++/*! FIXME: put this definition in a relevant header (e.g. as (evqid)+1) */ ++#define EFAB_EVQ_OWNER_ID(evqid) ((evqid)) ++ ++void ++efrm_vi_rm_init_dmaq(struct vi_resource *virs, int queue_type, ++ struct efhw_nic *nic) ++{ ++ int instance; ++ int evq_instance; ++ efhw_buffer_addr_t buf_addr; ++ ++ instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle); ++ evq_instance = EFRM_RESOURCE_INSTANCE(virs->evq_virs->rs.rs_handle); ++ ++ buf_addr = virs->dmaq_buf_tbl_alloc[queue_type].base; ++ ++ if (queue_type == EFRM_VI_RM_DMA_QUEUE_TX) { ++ efhw_nic_dmaq_tx_q_init(nic, ++ instance, /* dmaq */ ++ evq_instance, /* evq */ ++ EFAB_EVQ_OWNER_ID(evq_instance), /* owner */ ++ virs->dmaq_tag[queue_type], /* tag */ ++ virs->dmaq_capacity[queue_type], /* size of queue */ ++ buf_addr, /* buffer index */ ++ virs->flags); /* user specified Q attrs */ ++ } else { ++ efhw_nic_dmaq_rx_q_init(nic, ++ instance, /* dmaq */ ++ evq_instance, /* evq */ ++ EFAB_EVQ_OWNER_ID(evq_instance), /* owner */ ++ virs->dmaq_tag[queue_type], /* tag */ ++ virs->dmaq_capacity[queue_type], /* size of queue */ ++ buf_addr, /* buffer index */ ++ virs->flags); /* user specified Q attrs */ ++ } ++} ++ ++static int ++efrm_vi_rm_init_or_fini_dmaq(struct vi_resource *virs, ++ int queue_type, int init, ++ struct efhw_nic *nic) ++{ ++ int rc; ++ int instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle); ++ uint32_t buf_bytes; ++ struct vi_resource_nic_info *nic_info = &virs->nic_info; ++ int page_order; ++ uint32_t num_pages; ++ struct efhw_iopages *iobuff; ++ ++ if (!init) ++ goto destroy; ++ ++ /* Ignore disabled queues. */ ++ if (virs->dmaq_capacity[queue_type] == 0) { ++ if (queue_type == EFRM_VI_RM_DMA_QUEUE_TX) ++ efhw_nic_dmaq_tx_q_disable(nic, instance); ++ else ++ efhw_nic_dmaq_rx_q_disable(nic, instance); ++ return 0; ++ } ++ ++ buf_bytes = (queue_type == EFRM_VI_RM_DMA_QUEUE_TX ++ ? efrm_vi_rm_txq_bytes(virs) ++ : efrm_vi_rm_rxq_bytes(virs)); ++ ++ page_order = get_order(buf_bytes); ++ ++ rc = efhw_iopages_alloc(nic, &nic_info->dmaq_pages[queue_type], ++ page_order); ++ if (rc != 0) { ++ EFRM_ERR("%s: Failed to allocate %s DMA buffer.", __func__, ++ dmaq_names[queue_type]); ++ goto fail_iopages; ++ } ++ ++ num_pages = 1 << page_order; ++ iobuff = &nic_info->dmaq_pages[queue_type]; ++ efhw_nic_buffer_table_set_n(nic, ++ virs->dmaq_buf_tbl_alloc[queue_type].base, ++ efhw_iopages_dma_addr(iobuff), ++ EFHW_NIC_PAGE_SIZE, 0, num_pages, 0); ++ ++ falcon_nic_buffer_table_confirm(nic); ++ ++ virs->mem_mmap_bytes += roundup(buf_bytes, PAGE_SIZE); ++ ++ /* Make sure there is an event queue. */ ++ if (virs->evq_virs->evq_capacity <= 0) { ++ EFRM_ERR("%s: Cannot use empty event queue for %s DMA", ++ __func__, dmaq_names[queue_type]); ++ rc = -EINVAL; ++ goto fail_evq; ++ } ++ ++ efrm_vi_rm_init_dmaq(virs, queue_type, nic); ++ ++ return 0; ++ ++destroy: ++ rc = 0; ++ ++ /* Ignore disabled queues. */ ++ if (virs->dmaq_capacity[queue_type] == 0) ++ return 0; ++ ++ /* Ensure TX pacing turned off -- queue flush doesn't reset this. */ ++ if (queue_type == EFRM_VI_RM_DMA_QUEUE_TX) ++ falcon_nic_pace(nic, instance, 0); ++ ++ /* No need to disable the queue here. Nobody is using it anyway. */ ++ ++fail_evq: ++ efhw_iopages_free(nic, &nic_info->dmaq_pages[queue_type]); ++fail_iopages: ++ ++ return rc; ++} ++ ++static int ++efrm_vi_rm_init_or_fini_nic(struct vi_resource *virs, int init, ++ struct efhw_nic *nic) ++{ ++ int rc; ++#ifndef NDEBUG ++ int instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle); ++#endif ++ ++ if (!init) ++ goto destroy; ++ ++ rc = efrm_vi_rm_init_evq(virs, nic); ++ if (rc != 0) ++ goto fail_evq; ++ ++ rc = efrm_vi_rm_init_or_fini_dmaq(virs, EFRM_VI_RM_DMA_QUEUE_TX, ++ init, nic); ++ if (rc != 0) ++ goto fail_txq; ++ ++ rc = efrm_vi_rm_init_or_fini_dmaq(virs, EFRM_VI_RM_DMA_QUEUE_RX, ++ init, nic); ++ if (rc != 0) ++ goto fail_rxq; ++ ++ /* Allocate space for the control page. */ ++ EFRM_ASSERT(falcon_tx_dma_page_offset(instance) < PAGE_SIZE); ++ EFRM_ASSERT(falcon_rx_dma_page_offset(instance) < PAGE_SIZE); ++ EFRM_ASSERT(falcon_timer_page_offset(instance) < PAGE_SIZE); ++ virs->bar_mmap_bytes += PAGE_SIZE; ++ ++ return 0; ++ ++destroy: ++ rc = 0; ++ ++ efrm_vi_rm_init_or_fini_dmaq(virs, EFRM_VI_RM_DMA_QUEUE_RX, ++ false, nic); ++fail_rxq: ++ ++ efrm_vi_rm_init_or_fini_dmaq(virs, EFRM_VI_RM_DMA_QUEUE_TX, ++ false, nic); ++fail_txq: ++ ++ efrm_vi_rm_fini_evq(virs, nic); ++fail_evq: ++ ++ EFRM_ASSERT(rc != 0 || !init); ++ return rc; ++} ++ ++static int ++efrm_vi_resource_alloc_or_free(struct efrm_client *client, ++ int alloc, struct vi_resource *evq_virs, ++ uint16_t vi_flags, int32_t evq_capacity, ++ int32_t txq_capacity, int32_t rxq_capacity, ++ uint8_t tx_q_tag, uint8_t rx_q_tag, ++ struct vi_resource **virs_in_out) ++{ ++ struct efhw_nic *nic = client->nic; ++ struct vi_resource *virs; ++ int rc; ++ int instance; ++ ++ EFRM_ASSERT(virs_in_out); ++ EFRM_ASSERT(efrm_vi_manager); ++ EFRM_RESOURCE_MANAGER_ASSERT_VALID(&efrm_vi_manager->rm); ++ ++ if (!alloc) ++ goto destroy; ++ ++ rx_q_tag &= (1 << TX_DESCQ_LABEL_WIDTH) - 1; ++ tx_q_tag &= (1 << RX_DESCQ_LABEL_WIDTH) - 1; ++ ++ virs = kmalloc(sizeof(*virs), GFP_KERNEL); ++ if (virs == NULL) { ++ EFRM_ERR("%s: Error allocating VI resource object", ++ __func__); ++ rc = -ENOMEM; ++ goto fail_alloc; ++ } ++ memset(virs, 0, sizeof(*virs)); ++ ++ /* Some macros make the assumption that the struct efrm_resource is ++ * the first member of a struct vi_resource. */ ++ EFRM_ASSERT(&virs->rs == (struct efrm_resource *) (virs)); ++ ++ instance = efrm_vi_rm_alloc_id(vi_flags, evq_capacity); ++ if (instance < 0) { ++ /* Clear out the close list... */ ++ efrm_vi_rm_salvage_flushed_vis(); ++ instance = efrm_vi_rm_alloc_id(vi_flags, evq_capacity); ++ if (instance >= 0) ++ EFRM_TRACE("%s: Salvaged a closed VI.", __func__); ++ } ++ ++ if (instance < 0) { ++ /* Could flush resources and try again here. */ ++ EFRM_ERR("%s: Out of appropriate VI resources", __func__); ++ rc = -EBUSY; ++ goto fail_alloc_id; ++ } ++ ++ EFRM_TRACE("%s: new VI ID %d", __func__, instance); ++ efrm_resource_init(&virs->rs, EFRM_RESOURCE_VI, instance); ++ ++ /* Start with one reference. Any external VIs using the EVQ of this ++ * resource will increment this reference rather than the resource ++ * reference to avoid DMAQ flushes from waiting for other DMAQ ++ * flushes to complete. When the resource reference goes to zero, ++ * the DMAQ flush happens. When the flush completes, this reference ++ * is decremented. When this reference reaches zero, the instance ++ * is freed. */ ++ atomic_set(&virs->evq_refs, 1); ++ ++ virs->bar_mmap_bytes = 0; ++ virs->mem_mmap_bytes = 0; ++ virs->evq_capacity = evq_capacity; ++ virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_TX] = txq_capacity; ++ virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_RX] = rxq_capacity; ++ virs->dmaq_tag[EFRM_VI_RM_DMA_QUEUE_TX] = tx_q_tag; ++ virs->dmaq_tag[EFRM_VI_RM_DMA_QUEUE_RX] = rx_q_tag; ++ virs->flags = vi_flags; ++ INIT_LIST_HEAD(&virs->tx_flush_link); ++ INIT_LIST_HEAD(&virs->rx_flush_link); ++ virs->tx_flushing = 0; ++ virs->rx_flushing = 0; ++ ++ /* Adjust the queue sizes. */ ++ rc = efrm_vi_rm_adjust_alloc_request(virs, nic); ++ if (rc != 0) ++ goto fail_adjust_request; ++ ++ /* Attach the EVQ early so that we can ensure that the NIC sets ++ * match. */ ++ if (evq_virs == NULL) { ++ evq_virs = virs; ++ EFRM_TRACE("%s: " EFRM_RESOURCE_FMT ++ " has no external event queue", __func__, ++ EFRM_RESOURCE_PRI_ARG(virs->rs.rs_handle)); ++ } else { ++ /* Make sure the resource managers are the same. */ ++ if (EFRM_RESOURCE_TYPE(evq_virs->rs.rs_handle) != ++ EFRM_RESOURCE_VI) { ++ EFRM_ERR("%s: Mismatched owner for event queue VI " ++ EFRM_RESOURCE_FMT, __func__, ++ EFRM_RESOURCE_PRI_ARG(evq_virs->rs.rs_handle)); ++ return -EINVAL; ++ } ++ EFRM_ASSERT(atomic_read(&evq_virs->evq_refs) != 0); ++ efrm_vi_rm_get_ref(evq_virs); ++ EFRM_TRACE("%s: " EFRM_RESOURCE_FMT " uses event queue " ++ EFRM_RESOURCE_FMT, ++ __func__, ++ EFRM_RESOURCE_PRI_ARG(virs->rs.rs_handle), ++ EFRM_RESOURCE_PRI_ARG(evq_virs->rs.rs_handle)); ++ } ++ virs->evq_virs = evq_virs; ++ ++ rc = efrm_vi_rm_alloc_or_free_buffer_table(virs, true); ++ if (rc != 0) ++ goto fail_buffer_table; ++ ++ rc = efrm_vi_rm_init_or_fini_nic(virs, true, nic); ++ if (rc != 0) ++ goto fail_init_nic; ++ ++ efrm_client_add_resource(client, &virs->rs); ++ *virs_in_out = virs; ++ EFRM_TRACE("%s: Allocated " EFRM_RESOURCE_FMT, __func__, ++ EFRM_RESOURCE_PRI_ARG(virs->rs.rs_handle)); ++ return 0; ++ ++destroy: ++ virs = *virs_in_out; ++ EFRM_RESOURCE_ASSERT_VALID(&virs->rs, 1); ++ instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle); ++ ++ EFRM_TRACE("%s: Freeing %d", __func__, ++ EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle)); ++ ++ /* Destroying the VI. The reference count must be zero. */ ++ EFRM_ASSERT(atomic_read(&virs->evq_refs) == 0); ++ ++ /* The EVQ should have gone (and DMA disabled) so that this ++ * function can't be re-entered to destroy the EVQ VI. */ ++ EFRM_ASSERT(virs->evq_virs == NULL); ++ rc = 0; ++ ++fail_init_nic: ++ efrm_vi_rm_init_or_fini_nic(virs, false, nic); ++ ++ efrm_vi_rm_alloc_or_free_buffer_table(virs, false); ++fail_buffer_table: ++ ++ efrm_vi_rm_detach_evq(virs); ++ ++fail_adjust_request: ++ ++ EFRM_ASSERT(virs->evq_callback_fn == NULL); ++ EFRM_TRACE("%s: delete VI ID %d", __func__, instance); ++ efrm_vi_rm_free_id(instance); ++fail_alloc_id: ++ if (!alloc) ++ efrm_client_put(virs->rs.rs_client); ++ EFRM_DO_DEBUG(memset(virs, 0, sizeof(*virs))); ++ kfree(virs); ++fail_alloc: ++ *virs_in_out = NULL; ++ ++ return rc; ++} ++ ++/*** Resource object ****************************************************/ ++ ++int ++efrm_vi_resource_alloc(struct efrm_client *client, ++ struct vi_resource *evq_virs, ++ uint16_t vi_flags, int32_t evq_capacity, ++ int32_t txq_capacity, int32_t rxq_capacity, ++ uint8_t tx_q_tag, uint8_t rx_q_tag, ++ struct vi_resource **virs_out, ++ uint32_t *out_io_mmap_bytes, ++ uint32_t *out_mem_mmap_bytes, ++ uint32_t *out_txq_capacity, uint32_t *out_rxq_capacity) ++{ ++ int rc; ++ EFRM_ASSERT(client != NULL); ++ rc = efrm_vi_resource_alloc_or_free(client, true, evq_virs, vi_flags, ++ evq_capacity, txq_capacity, ++ rxq_capacity, tx_q_tag, rx_q_tag, ++ virs_out); ++ if (rc == 0) { ++ if (out_io_mmap_bytes != NULL) ++ *out_io_mmap_bytes = (*virs_out)->bar_mmap_bytes; ++ if (out_mem_mmap_bytes != NULL) ++ *out_mem_mmap_bytes = (*virs_out)->mem_mmap_bytes; ++ if (out_txq_capacity != NULL) ++ *out_txq_capacity = ++ (*virs_out)->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_TX]; ++ if (out_rxq_capacity != NULL) ++ *out_rxq_capacity = ++ (*virs_out)->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_RX]; ++ } ++ ++ return rc; ++} ++EXPORT_SYMBOL(efrm_vi_resource_alloc); ++ ++void efrm_vi_rm_free_flushed_resource(struct vi_resource *virs) ++{ ++ EFRM_ASSERT(virs != NULL); ++ EFRM_ASSERT(virs->rs.rs_ref_count == 0); ++ ++ EFRM_TRACE("%s: " EFRM_RESOURCE_FMT, __func__, ++ EFRM_RESOURCE_PRI_ARG(virs->rs.rs_handle)); ++ /* release the associated event queue then drop our own reference ++ * count */ ++ efrm_vi_rm_detach_evq(virs); ++ efrm_vi_rm_drop_ref(virs); ++} +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/vi_resource_event.c 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,250 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file contains event handling for VI resource. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * Certain parts of the driver were implemented by ++ * Alexandra Kossovsky ++ * OKTET Labs Ltd, Russia, ++ * http://oktetlabs.ru, ++ * by request of Solarflare Communications ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "efrm_internal.h" ++ ++ ++static inline int ++efrm_eventq_bytes(struct vi_resource *virs) ++{ ++ return efrm_vi_rm_evq_bytes(virs); ++} ++ ++ ++static inline efhw_event_t * ++efrm_eventq_base(struct vi_resource *virs) ++{ ++ struct eventq_resource_hardware *hw; ++ hw = &(virs->nic_info.evq_pages); ++ return (efhw_event_t *) (efhw_iopages_ptr(&(hw->iobuff)) + ++ hw->iobuff_off); ++} ++ ++ ++void ++efrm_eventq_request_wakeup(struct vi_resource *virs, unsigned current_ptr) ++{ ++ struct efhw_nic *nic = virs->rs.rs_client->nic; ++ int next_i; ++ next_i = ((current_ptr / sizeof(efhw_event_t)) & ++ (virs->evq_capacity - 1)); ++ ++ efhw_nic_wakeup_request(nic, efrm_eventq_dma_addr(virs), next_i, ++ EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle)); ++} ++EXPORT_SYMBOL(efrm_eventq_request_wakeup); ++ ++void efrm_eventq_reset(struct vi_resource *virs) ++{ ++ struct efhw_nic *nic = virs->rs.rs_client->nic; ++ int instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle); ++ ++ EFRM_ASSERT(virs->evq_capacity != 0); ++ ++ /* FIXME: Protect against concurrent resets. */ ++ ++ efhw_nic_event_queue_disable(nic, instance, 0); ++ ++ memset(efrm_eventq_base(virs), EFHW_CLEAR_EVENT_VALUE, ++ efrm_eventq_bytes(virs)); ++ efhw_nic_event_queue_enable(nic, instance, virs->evq_capacity, ++ efrm_eventq_dma_addr(virs), ++ virs->nic_info.evq_pages. ++ buf_tbl_alloc.base, ++ instance < 64); ++ EFRM_TRACE("%s: " EFRM_RESOURCE_FMT, __func__, ++ EFRM_RESOURCE_PRI_ARG(virs->rs.rs_handle)); ++} ++EXPORT_SYMBOL(efrm_eventq_reset); ++ ++int ++efrm_eventq_register_callback(struct vi_resource *virs, ++ void (*handler) (void *, int, ++ struct efhw_nic *nic), ++ void *arg) ++{ ++ struct efrm_nic_per_vi *cb_info; ++ int instance; ++ int bit; ++ ++ EFRM_RESOURCE_ASSERT_VALID(&virs->rs, 0); ++ EFRM_ASSERT(virs->evq_capacity != 0); ++ EFRM_ASSERT(handler != NULL); ++ ++ /* ?? TODO: Get rid of this test when client is compulsory. */ ++ if (virs->rs.rs_client == NULL) { ++ EFRM_ERR("%s: no client", __func__); ++ return -EINVAL; ++ } ++ ++ virs->evq_callback_arg = arg; ++ virs->evq_callback_fn = handler; ++ instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle); ++ cb_info = &efrm_nic(virs->rs.rs_client->nic)->vis[instance]; ++ ++ /* The handler can be set only once. */ ++ bit = test_and_set_bit(VI_RESOURCE_EVQ_STATE_CALLBACK_REGISTERED, ++ &cb_info->state); ++ if (bit) ++ return -EBUSY; ++ cb_info->vi = virs; ++ ++ return 0; ++} ++EXPORT_SYMBOL(efrm_eventq_register_callback); ++ ++void efrm_eventq_kill_callback(struct vi_resource *virs) ++{ ++ struct efrm_nic_per_vi *cb_info; ++ int32_t evq_state; ++ int instance; ++ int bit; ++ ++ EFRM_RESOURCE_ASSERT_VALID(&virs->rs, 0); ++ EFRM_ASSERT(virs->evq_capacity != 0); ++ EFRM_ASSERT(virs->rs.rs_client != NULL); ++ ++ instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle); ++ cb_info = &efrm_nic(virs->rs.rs_client->nic)->vis[instance]; ++ cb_info->vi = NULL; ++ ++ /* Disable the timer. */ ++ efhw_nic_event_queue_disable(virs->rs.rs_client->nic, ++ instance, /*timer_only */ 1); ++ ++ /* Disable the callback. */ ++ bit = test_and_clear_bit(VI_RESOURCE_EVQ_STATE_CALLBACK_REGISTERED, ++ &cb_info->state); ++ EFRM_ASSERT(bit); /* do not call me twice! */ ++ ++ /* Spin until the callback is complete. */ ++ do { ++ rmb(); ++ ++ udelay(1); ++ evq_state = cb_info->state; ++ } while ((evq_state & VI_RESOURCE_EVQ_STATE(BUSY))); ++ ++ virs->evq_callback_fn = NULL; ++} ++EXPORT_SYMBOL(efrm_eventq_kill_callback); ++ ++static void ++efrm_eventq_do_callback(struct efhw_nic *nic, unsigned instance, ++ bool is_timeout) ++{ ++ struct efrm_nic *rnic = efrm_nic(nic); ++ void (*handler) (void *, int is_timeout, struct efhw_nic *nic); ++ void *arg; ++ struct efrm_nic_per_vi *cb_info; ++ int32_t evq_state; ++ int32_t new_evq_state; ++ struct vi_resource *virs; ++ int bit; ++ ++ EFRM_ASSERT(efrm_vi_manager); ++ ++ cb_info = &rnic->vis[instance]; ++ ++ /* Set the BUSY bit and clear WAKEUP_PENDING. Do this ++ * before waking up the sleeper to avoid races. */ ++ while (1) { ++ evq_state = cb_info->state; ++ new_evq_state = evq_state; ++ ++ if ((evq_state & VI_RESOURCE_EVQ_STATE(BUSY)) != 0) { ++ EFRM_ERR("%s:%d: evq_state[%d] corrupted!", ++ __func__, __LINE__, instance); ++ return; ++ } ++ ++ if (!is_timeout) ++ new_evq_state &= ~VI_RESOURCE_EVQ_STATE(WAKEUP_PENDING); ++ ++ if (evq_state & VI_RESOURCE_EVQ_STATE(CALLBACK_REGISTERED)) { ++ new_evq_state |= VI_RESOURCE_EVQ_STATE(BUSY); ++ virs = cb_info->vi; ++ if (cmpxchg(&cb_info->state, evq_state, ++ new_evq_state) == evq_state) ++ break; ++ } else { ++ /* Just update the state if necessary. */ ++ if (new_evq_state == evq_state || ++ cmpxchg(&cb_info->state, evq_state, ++ new_evq_state) == evq_state) ++ return; ++ } ++ } ++ ++ if (virs) { ++ handler = virs->evq_callback_fn; ++ arg = virs->evq_callback_arg; ++ EFRM_ASSERT(handler != NULL); ++ handler(arg, is_timeout, nic); ++ } ++ ++ /* Clear the BUSY bit. */ ++ bit = ++ test_and_clear_bit(VI_RESOURCE_EVQ_STATE_BUSY, ++ &cb_info->state); ++ if (!bit) { ++ EFRM_ERR("%s:%d: evq_state corrupted!", ++ __func__, __LINE__); ++ } ++} ++ ++void efrm_handle_wakeup_event(struct efhw_nic *nic, unsigned instance) ++{ ++ efrm_eventq_do_callback(nic, instance, false); ++} ++ ++void efrm_handle_timeout_event(struct efhw_nic *nic, unsigned instance) ++{ ++ efrm_eventq_do_callback(nic, instance, true); ++} ++ ++void efrm_handle_sram_event(struct efhw_nic *nic) ++{ ++ if (nic->buf_commit_outstanding > 0) ++ nic->buf_commit_outstanding--; ++} +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/vi_resource_flush.c 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,483 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file contains DMA queue flushing of VI resources. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * Certain parts of the driver were implemented by ++ * Alexandra Kossovsky ++ * OKTET Labs Ltd, Russia, ++ * http://oktetlabs.ru, ++ * by request of Solarflare Communications ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "efrm_internal.h" ++ ++ ++/* can fail as workitem can already be scheuled -- ignore failure */ ++#define EFRM_VI_RM_DELAYED_FREE(manager) \ ++ queue_work(manager->workqueue, &manager->work_item) ++ ++static const int flush_fifo_hwm = 8 /* TODO should be a HW specific const */ ; ++ ++static void ++efrm_vi_resource_rx_flush_done(struct vi_resource *virs, bool *completed) ++{ ++ /* We should only get a flush event if there is a flush ++ * outstanding. */ ++ EFRM_ASSERT(virs->rx_flush_outstanding); ++ ++ virs->rx_flush_outstanding = 0; ++ virs->rx_flushing = 0; ++ ++ list_del(&virs->rx_flush_link); ++ efrm_vi_manager->rx_flush_outstanding_count--; ++ ++ if (virs->tx_flushing == 0) { ++ list_add_tail(&virs->rx_flush_link, ++ &efrm_vi_manager->close_pending); ++ *completed = 1; ++ } ++} ++ ++static void ++efrm_vi_resource_tx_flush_done(struct vi_resource *virs, bool *completed) ++{ ++ /* We should only get a flush event if there is a flush ++ * outstanding. */ ++ EFRM_ASSERT(virs->tx_flushing); ++ ++ virs->tx_flushing = 0; ++ ++ list_del(&virs->tx_flush_link); ++ ++ if (virs->rx_flushing == 0) { ++ list_add_tail(&virs->rx_flush_link, ++ &efrm_vi_manager->close_pending); ++ *completed = 1; ++ } ++} ++ ++static void ++efrm_vi_resource_issue_rx_flush(struct vi_resource *virs, bool *completed) ++{ ++ struct efhw_nic *nic = virs->rs.rs_client->nic; ++ int instance; ++ int rc; ++ ++ instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle); ++ ++ list_add_tail(&virs->rx_flush_link, ++ &efrm_vi_manager->rx_flush_outstanding_list); ++ virs->rx_flush_outstanding = virs->rx_flushing; ++ efrm_vi_manager->rx_flush_outstanding_count++; ++ ++ EFRM_TRACE("%s: rx queue %d flush requested for nic %d", ++ __func__, instance, nic->index); ++ rc = efhw_nic_flush_rx_dma_channel(nic, instance); ++ if (rc == -EAGAIN) ++ efrm_vi_resource_rx_flush_done(virs, completed); ++} ++ ++static void ++efrm_vi_resource_issue_tx_flush(struct vi_resource *virs, bool *completed) ++{ ++ struct efhw_nic *nic = virs->rs.rs_client->nic; ++ int instance; ++ int rc; ++ ++ instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle); ++ ++ list_add_tail(&virs->tx_flush_link, ++ &efrm_vi_manager->tx_flush_outstanding_list); ++ ++ EFRM_TRACE("%s: tx queue %d flush requested for nic %d", ++ __func__, instance, nic->index); ++ rc = efhw_nic_flush_tx_dma_channel(nic, instance); ++ if (rc == -EAGAIN) ++ efrm_vi_resource_tx_flush_done(virs, completed); ++} ++ ++static void efrm_vi_resource_process_waiting_flushes(bool *completed) ++{ ++ struct vi_resource *virs; ++ ++ while (efrm_vi_manager->rx_flush_outstanding_count < flush_fifo_hwm && ++ !list_empty(&efrm_vi_manager->rx_flush_waiting_list)) { ++ virs = ++ list_entry(list_pop ++ (&efrm_vi_manager->rx_flush_waiting_list), ++ struct vi_resource, rx_flush_link); ++ efrm_vi_resource_issue_rx_flush(virs, completed); ++ } ++} ++ ++#if BUG7916_WORKAROUND || BUG5302_WORKAROUND ++static void ++efrm_vi_resource_flush_retry_vi(struct vi_resource *virs, ++ int64_t time_now, bool *completed) ++{ ++ struct efhw_nic *nic; ++ int instance; ++ ++ instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle); ++ ++ virs->flush_count++; ++ virs->flush_time = time_now; ++ nic = virs->rs.rs_client->nic; ++ ++#if BUG7916_WORKAROUND ++ if (virs->rx_flush_outstanding) { ++ EFRM_TRACE("%s: Retrying RX flush on instance %d", ++ __func__, instance); ++ ++ list_del(&virs->rx_flush_link); ++ efrm_vi_manager->rx_flush_outstanding_count--; ++ efrm_vi_resource_issue_rx_flush(virs, completed); ++ efrm_vi_resource_process_waiting_flushes(completed); ++ } ++#endif ++ ++#if BUG5302_WORKAROUND ++ if (virs->tx_flushing) { ++ if (virs->flush_count > 5) { ++ EFRM_TRACE("%s: VI resource stuck flush pending " ++ "(instance=%d, count=%d)", ++ __func__, instance, virs->flush_count); ++ falcon_clobber_tx_dma_ptrs(nic, instance); ++ } else { ++ EFRM_TRACE("%s: Retrying TX flush on instance %d", ++ __func__, instance); ++ } ++ ++ list_del(&virs->tx_flush_link); ++ efrm_vi_resource_issue_tx_flush(virs, completed); ++ } ++#endif ++} ++#endif ++ ++int efrm_vi_resource_flush_retry(struct vi_resource *virs) ++{ ++#if BUG7916_WORKAROUND || BUG5302_WORKAROUND ++ irq_flags_t lock_flags; ++ bool completed = false; ++ ++ if (virs->rx_flushing == 0 && virs->tx_flushing == 0) ++ return -EALREADY; ++ ++ spin_lock_irqsave(&efrm_vi_manager->rm.rm_lock, lock_flags); ++ efrm_vi_resource_flush_retry_vi(virs, get_jiffies_64(), &completed); ++ spin_unlock_irqrestore(&efrm_vi_manager->rm.rm_lock, lock_flags); ++ ++ if (completed) ++ EFRM_VI_RM_DELAYED_FREE(efrm_vi_manager); ++#endif ++ ++ return 0; ++} ++EXPORT_SYMBOL(efrm_vi_resource_flush_retry); ++ ++#if BUG7916_WORKAROUND || BUG5302_WORKAROUND ++/* resource manager lock should be taken before this call */ ++static void efrm_vi_handle_flush_loss(bool *completed) ++{ ++ struct list_head *pos, *temp; ++ struct vi_resource *virs; ++ int64_t time_now, time_pending; ++ ++ /* It's possible we miss flushes - the list is sorted in order we ++ * generate flushes, see if any are very old. It's also possible ++ * that we decide an endpoint is flushed even though we've not ++ * received all the flush events. We *should * mark as ++ * completed, reclaim and loop again. ?? ++ * THIS NEEDS BACKPORTING FROM THE FALCON branch ++ */ ++ time_now = get_jiffies_64(); ++ ++#if BUG7916_WORKAROUND ++ list_for_each_safe(pos, temp, ++ &efrm_vi_manager->rx_flush_outstanding_list) { ++ virs = container_of(pos, struct vi_resource, rx_flush_link); ++ ++ time_pending = time_now - virs->flush_time; ++ ++ /* List entries are held in reverse chronological order. Only ++ * process the old ones. */ ++ if (time_pending <= 0x100000000LL) ++ break; ++ ++ efrm_vi_resource_flush_retry_vi(virs, time_now, completed); ++ } ++#endif ++ ++#if BUG5302_WORKAROUND ++ list_for_each_safe(pos, temp, ++ &efrm_vi_manager->tx_flush_outstanding_list) { ++ virs = container_of(pos, struct vi_resource, tx_flush_link); ++ ++ time_pending = time_now - virs->flush_time; ++ ++ /* List entries are held in reverse chronological order. ++ * Only process the old ones. */ ++ if (time_pending <= 0x100000000LL) ++ break; ++ ++ efrm_vi_resource_flush_retry_vi(virs, time_now, completed); ++ } ++#endif ++} ++#endif ++ ++void ++efrm_vi_register_flush_callback(struct vi_resource *virs, ++ void (*handler)(void *), void *arg) ++{ ++ if (handler == NULL) { ++ virs->flush_callback_fn = handler; ++ wmb(); ++ virs->flush_callback_arg = arg; ++ } else { ++ virs->flush_callback_arg = arg; ++ wmb(); ++ virs->flush_callback_fn = handler; ++ } ++} ++EXPORT_SYMBOL(efrm_vi_register_flush_callback); ++ ++int efrm_pt_flush(struct vi_resource *virs) ++{ ++ int instance; ++ irq_flags_t lock_flags; ++ bool completed = false; ++ ++ instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle); ++ ++ EFRM_ASSERT(virs->rx_flushing == 0); ++ EFRM_ASSERT(virs->rx_flush_outstanding == 0); ++ EFRM_ASSERT(virs->tx_flushing == 0); ++ ++ EFRM_TRACE("%s: " EFRM_RESOURCE_FMT " EVQ=%d TXQ=%d RXQ=%d", ++ __func__, EFRM_RESOURCE_PRI_ARG(virs->rs.rs_handle), ++ virs->evq_capacity, ++ virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_TX], ++ virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_RX]); ++ ++ spin_lock_irqsave(&efrm_vi_manager->rm.rm_lock, lock_flags); ++ ++ if (virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_RX] != 0) ++ virs->rx_flushing = 1; ++ ++ if (virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_TX] != 0) ++ virs->tx_flushing = 1; ++ ++ /* Clean up immediately if there are no flushes. */ ++ if (virs->rx_flushing == 0 && virs->tx_flushing == 0) { ++ list_add_tail(&virs->rx_flush_link, ++ &efrm_vi_manager->close_pending); ++ completed = true; ++ } ++ ++ /* Issue the RX flush if possible or queue it for later. */ ++ if (virs->rx_flushing) { ++#if BUG7916_WORKAROUND || BUG5302_WORKAROUND ++ if (efrm_vi_manager->rx_flush_outstanding_count >= ++ flush_fifo_hwm) ++ efrm_vi_handle_flush_loss(&completed); ++#endif ++ if (efrm_vi_manager->rx_flush_outstanding_count >= ++ flush_fifo_hwm) { ++ list_add_tail(&virs->rx_flush_link, ++ &efrm_vi_manager->rx_flush_waiting_list); ++ } else { ++ efrm_vi_resource_issue_rx_flush(virs, &completed); ++ } ++ } ++ ++ /* Issue the TX flush. There's no limit to the number of ++ * outstanding TX flushes. */ ++ if (virs->tx_flushing) ++ efrm_vi_resource_issue_tx_flush(virs, &completed); ++ ++ virs->flush_time = get_jiffies_64(); ++ ++ spin_unlock_irqrestore(&efrm_vi_manager->rm.rm_lock, lock_flags); ++ ++ if (completed) ++ EFRM_VI_RM_DELAYED_FREE(efrm_vi_manager); ++ ++ return 0; ++} ++EXPORT_SYMBOL(efrm_pt_flush); ++ ++static void ++efrm_handle_rx_dmaq_flushed(struct efhw_nic *flush_nic, int instance, ++ bool *completed) ++{ ++ struct list_head *pos, *temp; ++ struct vi_resource *virs; ++ ++ list_for_each_safe(pos, temp, ++ &efrm_vi_manager->rx_flush_outstanding_list) { ++ virs = container_of(pos, struct vi_resource, rx_flush_link); ++ ++ if (instance == EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle)) { ++ efrm_vi_resource_rx_flush_done(virs, completed); ++ efrm_vi_resource_process_waiting_flushes(completed); ++ return; ++ } ++ } ++ EFRM_TRACE("%s: Unhandled rx flush event, nic %d, instance %d", ++ __func__, flush_nic->index, instance); ++} ++ ++static void ++efrm_handle_tx_dmaq_flushed(struct efhw_nic *flush_nic, int instance, ++ bool *completed) ++{ ++ struct list_head *pos, *temp; ++ struct vi_resource *virs; ++ ++ list_for_each_safe(pos, temp, ++ &efrm_vi_manager->tx_flush_outstanding_list) { ++ virs = container_of(pos, struct vi_resource, tx_flush_link); ++ ++ if (instance == EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle)) { ++ efrm_vi_resource_tx_flush_done(virs, completed); ++ return; ++ } ++ } ++ EFRM_TRACE("%s: Unhandled tx flush event, nic %d, instance %d", ++ __func__, flush_nic->index, instance); ++} ++ ++void ++efrm_handle_dmaq_flushed(struct efhw_nic *flush_nic, unsigned instance, ++ int rx_flush) ++{ ++ irq_flags_t lock_flags; ++ bool completed = false; ++ ++ EFRM_TRACE("%s: nic_i=%d instance=%d rx_flush=%d", __func__, ++ flush_nic->index, instance, rx_flush); ++ ++ spin_lock_irqsave(&efrm_vi_manager->rm.rm_lock, lock_flags); ++ ++ if (rx_flush) ++ efrm_handle_rx_dmaq_flushed(flush_nic, instance, &completed); ++ else ++ efrm_handle_tx_dmaq_flushed(flush_nic, instance, &completed); ++ ++#if BUG7916_WORKAROUND || BUG5302_WORKAROUND ++ efrm_vi_handle_flush_loss(&completed); ++#endif ++ ++ spin_unlock_irqrestore(&efrm_vi_manager->rm.rm_lock, lock_flags); ++ ++ if (completed) ++ EFRM_VI_RM_DELAYED_FREE(efrm_vi_manager); ++} ++ ++static void ++efrm_vi_rm_reinit_dmaqs(struct vi_resource *virs) ++{ ++ struct efhw_nic *nic = virs->rs.rs_client->nic; ++ ++ if (virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_TX] != 0) ++ efrm_vi_rm_init_dmaq(virs, EFRM_VI_RM_DMA_QUEUE_TX, nic); ++ if (virs->dmaq_capacity[EFRM_VI_RM_DMA_QUEUE_RX]) ++ efrm_vi_rm_init_dmaq(virs, EFRM_VI_RM_DMA_QUEUE_RX, nic); ++} ++ ++/* free any PT endpoints whose flush has now complete */ ++void efrm_vi_rm_delayed_free(struct work_struct *data) ++{ ++ irq_flags_t lock_flags; ++ struct list_head close_pending; ++ struct vi_resource *virs; ++ ++ EFRM_RESOURCE_MANAGER_ASSERT_VALID(&efrm_vi_manager->rm); ++ ++ spin_lock_irqsave(&efrm_vi_manager->rm.rm_lock, lock_flags); ++ list_replace_init(&efrm_vi_manager->close_pending, &close_pending); ++ spin_unlock_irqrestore(&efrm_vi_manager->rm.rm_lock, lock_flags); ++ ++ EFRM_TRACE("%s: %p", __func__, efrm_vi_manager); ++ while (!list_empty(&close_pending)) { ++ virs = ++ list_entry(list_pop(&close_pending), struct vi_resource, ++ rx_flush_link); ++ EFRM_TRACE("%s: flushed VI instance=%d", __func__, ++ EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle)); ++ ++ if (virs->flush_callback_fn != NULL) { ++ efrm_vi_rm_reinit_dmaqs(virs); ++ virs->flush_callback_fn(virs->flush_callback_arg); ++ } else ++ efrm_vi_rm_free_flushed_resource(virs); ++ } ++} ++ ++void efrm_vi_rm_salvage_flushed_vis(void) ++{ ++#if BUG7916_WORKAROUND || BUG5302_WORKAROUND ++ irq_flags_t lock_flags; ++ bool completed; ++ ++ spin_lock_irqsave(&efrm_vi_manager->rm.rm_lock, lock_flags); ++ efrm_vi_handle_flush_loss(&completed); ++ spin_unlock_irqrestore(&efrm_vi_manager->rm.rm_lock, lock_flags); ++#endif ++ ++ efrm_vi_rm_delayed_free(&efrm_vi_manager->work_item); ++} ++ ++void efrm_vi_resource_free(struct vi_resource *virs) ++{ ++ efrm_vi_register_flush_callback(virs, NULL, NULL); ++ efrm_pt_flush(virs); ++} ++EXPORT_SYMBOL(efrm_vi_resource_free); ++ ++ ++void efrm_vi_resource_release(struct vi_resource *virs) ++{ ++ if (__efrm_resource_release(&virs->rs)) ++ efrm_vi_resource_free(virs); ++} ++EXPORT_SYMBOL(efrm_vi_resource_release); ++ ++/* ++ * vi: sw=8:ai:aw ++ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-04-21/drivers/net/sfc/sfc_resource/vi_resource_manager.c 2008-07-17 16:18:07.000000000 +0200 +@@ -0,0 +1,231 @@ ++/**************************************************************************** ++ * Driver for Solarflare network controllers - ++ * resource management for Xen backend, OpenOnload, etc ++ * (including support for SFE4001 10GBT NIC) ++ * ++ * This file contains the VI resource manager. ++ * ++ * Copyright 2005-2007: Solarflare Communications Inc, ++ * 9501 Jeronimo Road, Suite 250, ++ * Irvine, CA 92618, USA ++ * ++ * Developed and maintained by Solarflare Communications: ++ * ++ * ++ * ++ * Certain parts of the driver were implemented by ++ * Alexandra Kossovsky ++ * OKTET Labs Ltd, Russia, ++ * http://oktetlabs.ru, ++ * by request of Solarflare Communications ++ * ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation, incorporated herein by reference. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ **************************************************************************** ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include "efrm_internal.h" ++ ++ ++int efrm_pt_pace(struct vi_resource *virs, unsigned int val) ++{ ++ struct efhw_nic *nic = virs->rs.rs_client->nic; ++ int instance; ++ ++ EFRM_RESOURCE_ASSERT_VALID(&virs->rs, 0); ++ instance = EFRM_RESOURCE_INSTANCE(virs->rs.rs_handle); ++ falcon_nic_pace(nic, instance, val); ++ EFRM_TRACE("%s[%d]=%d DONE", __func__, instance, val); ++ return 0; ++} ++EXPORT_SYMBOL(efrm_pt_pace); ++ ++/*** Resource manager creation/destruction *******************************/ ++ ++static void efrm_vi_rm_dtor(struct efrm_resource_manager *rm); ++ ++static int ++efrm_create_or_destroy_vi_resource_manager( ++ struct efrm_resource_manager **rm_in_out, ++ const struct vi_resource_dimensions *dims, ++ bool destroy) ++{ ++ struct vi_resource *virs; ++ struct list_head *pos, *temp; ++ struct list_head flush_pending; ++ irq_flags_t lock_flags; ++ int rc; ++ unsigned dmaq_min, dmaq_lim; ++ ++ EFRM_ASSERT(rm_in_out); ++ ++ if (destroy) ++ goto destroy; ++ ++ EFRM_ASSERT(dims); ++ EFRM_NOTICE("vi_resource_manager: evq_int=%u-%u evq_timer=%u-%u", ++ dims->evq_int_min, dims->evq_int_lim, ++ dims->evq_timer_min, dims->evq_timer_lim); ++ EFRM_NOTICE("vi_resource_manager: rxq=%u-%u txq=%u-%u", ++ dims->rxq_min, dims->rxq_lim, ++ dims->txq_min, dims->txq_lim); ++ ++ efrm_vi_manager = kmalloc(sizeof(*efrm_vi_manager), GFP_KERNEL); ++ if (efrm_vi_manager == NULL) { ++ rc = -ENOMEM; ++ goto fail_alloc; ++ } ++ ++ memset(efrm_vi_manager, 0, sizeof(*efrm_vi_manager)); ++ ++ efrm_vi_manager->iscsi_dmaq_instance_is_free = true; ++ ++ dmaq_min = max(dims->rxq_min, dims->txq_min); ++ dmaq_lim = min(dims->rxq_lim, dims->txq_lim); ++ ++ efrm_vi_manager->with_timer_base = ++ max(dmaq_min, dims->evq_timer_min); ++ efrm_vi_manager->with_timer_limit = ++ min(dmaq_lim, dims->evq_timer_lim); ++ rc = efrm_kfifo_id_ctor(&efrm_vi_manager->instances_with_timer, ++ efrm_vi_manager->with_timer_base, ++ efrm_vi_manager->with_timer_limit, ++ &efrm_vi_manager->rm.rm_lock); ++ if (rc < 0) ++ goto fail_with_timer_id_pool; ++ ++ efrm_vi_manager->with_interrupt_base = ++ max(dmaq_min, dims->evq_int_min); ++ efrm_vi_manager->with_interrupt_limit = ++ min(dmaq_lim, dims->evq_int_lim); ++ efrm_vi_manager->with_interrupt_limit = ++ max(efrm_vi_manager->with_interrupt_limit, ++ efrm_vi_manager->with_interrupt_base); ++ rc = efrm_kfifo_id_ctor(&efrm_vi_manager->instances_with_interrupt, ++ efrm_vi_manager->with_interrupt_base, ++ efrm_vi_manager->with_interrupt_limit, ++ &efrm_vi_manager->rm.rm_lock); ++ if (rc < 0) ++ goto fail_with_int_id_pool; ++ ++ INIT_LIST_HEAD(&efrm_vi_manager->rx_flush_waiting_list); ++ INIT_LIST_HEAD(&efrm_vi_manager->rx_flush_outstanding_list); ++ INIT_LIST_HEAD(&efrm_vi_manager->tx_flush_outstanding_list); ++ efrm_vi_manager->rx_flush_outstanding_count = 0; ++ ++ INIT_LIST_HEAD(&efrm_vi_manager->close_pending); ++ efrm_vi_manager->workqueue = create_workqueue("sfc_vi"); ++ if (efrm_vi_manager->workqueue == NULL) ++ goto fail_create_workqueue; ++ INIT_WORK(&efrm_vi_manager->work_item, efrm_vi_rm_delayed_free); ++ ++ /* NB. This must be the last step to avoid things getting tangled. ++ * efrm_resource_manager_dtor calls the vi_rm_dtor which ends up in ++ * this function. */ ++ rc = efrm_resource_manager_ctor(&efrm_vi_manager->rm, efrm_vi_rm_dtor, ++ "VI", EFRM_RESOURCE_VI); ++ if (rc < 0) ++ goto fail_rm_ctor; ++ ++ *rm_in_out = &efrm_vi_manager->rm; ++ return 0; ++ ++destroy: ++ rc = 0; ++ EFRM_RESOURCE_MANAGER_ASSERT_VALID(*rm_in_out); ++ ++ /* Abort outstanding flushes. Note, a VI resource can be on more ++ * than one of these lists. We handle this by starting with the TX ++ * list and then append VIs to this list if they aren't on the TX ++ * list already. A VI is on the TX flush list if tx_flushing ++ * is not empty. */ ++ spin_lock_irqsave(&efrm_vi_manager->rm.rm_lock, lock_flags); ++ ++ list_replace_init(&efrm_vi_manager->tx_flush_outstanding_list, ++ &flush_pending); ++ ++ list_for_each_safe(pos, temp, ++ &efrm_vi_manager->rx_flush_waiting_list) { ++ virs = container_of(pos, struct vi_resource, rx_flush_link); ++ ++ list_del(&virs->rx_flush_link); ++ if (virs->tx_flushing == 0) ++ list_add_tail(&virs->tx_flush_link, &flush_pending); ++ } ++ ++ list_for_each_safe(pos, temp, ++ &efrm_vi_manager->rx_flush_outstanding_list) { ++ virs = container_of(pos, struct vi_resource, rx_flush_link); ++ ++ list_del(&virs->rx_flush_link); ++ if (virs->tx_flushing == 0) ++ list_add_tail(&virs->tx_flush_link, &flush_pending); ++ } ++ ++ spin_unlock_irqrestore(&efrm_vi_manager->rm.rm_lock, lock_flags); ++ ++ while (!list_empty(&flush_pending)) { ++ virs = ++ list_entry(list_pop(&flush_pending), struct vi_resource, ++ tx_flush_link); ++ EFRM_TRACE("%s: found PT endpoint " EFRM_RESOURCE_FMT ++ " with flush pending [Tx=0x%x, Rx=0x%x, RxO=0x%x]", ++ __func__, ++ EFRM_RESOURCE_PRI_ARG(virs->rs.rs_handle), ++ virs->tx_flushing, ++ virs->rx_flushing, ++ virs->rx_flush_outstanding); ++ efrm_vi_rm_free_flushed_resource(virs); ++ } ++ ++fail_rm_ctor: ++ ++ /* Complete outstanding closes. */ ++ destroy_workqueue(efrm_vi_manager->workqueue); ++fail_create_workqueue: ++ EFRM_ASSERT(list_empty(&efrm_vi_manager->close_pending)); ++ kfifo_vfree(efrm_vi_manager->instances_with_interrupt); ++fail_with_int_id_pool: ++ ++ kfifo_vfree(efrm_vi_manager->instances_with_timer); ++fail_with_timer_id_pool: ++ ++ if (destroy) ++ return 0; ++ ++ EFRM_DO_DEBUG(memset(efrm_vi_manager, 0, sizeof(*efrm_vi_manager))); ++ kfree(efrm_vi_manager); ++fail_alloc: ++ ++ *rm_in_out = NULL; ++ EFRM_ERR("%s: failed rc=%d", __func__, rc); ++ return rc; ++} ++ ++int ++efrm_create_vi_resource_manager(struct efrm_resource_manager **rm_out, ++ const struct vi_resource_dimensions *dims) ++{ ++ return efrm_create_or_destroy_vi_resource_manager(rm_out, dims, false); ++} ++ ++static void efrm_vi_rm_dtor(struct efrm_resource_manager *rm) ++{ ++ efrm_create_or_destroy_vi_resource_manager(&rm, NULL, true); ++} diff --git a/sfc-set-arch b/sfc-set-arch new file mode 100644 index 0000000..a1ef8da --- /dev/null +++ b/sfc-set-arch @@ -0,0 +1,38 @@ +From: Kieran Mansley +Subject: set efhw_arch field of device type +References: bnc#489105 +Patch-mainline: n/a + +Acked-by: jbeulich@novell.com + +--- head-2009-04-07.orig/drivers/net/sfc/sfc_resource/ci/efhw/common.h 2009-04-07 14:39:57.000000000 +0200 ++++ head-2009-04-07/drivers/net/sfc/sfc_resource/ci/efhw/common.h 2009-04-07 15:02:05.000000000 +0200 +@@ -41,6 +41,10 @@ + + #include + ++enum efhw_arch { ++ EFHW_ARCH_FALCON, ++}; ++ + typedef uint32_t efhw_buffer_addr_t; + #define EFHW_BUFFER_ADDR_FMT "[ba:%"PRIx32"]" + +--- head-2009-04-07.orig/drivers/net/sfc/sfc_resource/nic.c 2009-04-07 14:39:57.000000000 +0200 ++++ head-2009-04-07/drivers/net/sfc/sfc_resource/nic.c 2009-04-07 15:02:05.000000000 +0200 +@@ -47,6 +47,7 @@ int efhw_device_type_init(struct efhw_de + switch (device_id) { + case 0x0703: + case 0x6703: ++ dt->arch = EFHW_ARCH_FALCON; + dt->variant = 'A'; + switch (class_revision) { + case 0: +@@ -60,6 +61,7 @@ int efhw_device_type_init(struct efhw_de + } + break; + case 0x0710: ++ dt->arch = EFHW_ARCH_FALCON; + dt->variant = 'B'; + switch (class_revision) { + case 2: diff --git a/tmem b/tmem new file mode 100644 index 0000000..0682a62 --- /dev/null +++ b/tmem @@ -0,0 +1,1388 @@ +Subject: Transcendent memory ("tmem") for Linux +From: http://xenbits.xensource.com/linux-2.6.18-xen.hg (tip 908:baeb818cd2dc) +Patch-mainline: n/a + +Tmem, when called from a tmem-capable (paravirtualized) guest, makes +use of otherwise unutilized ("fallow") memory to create and manage +pools of pages that can be accessed from the guest either as +"ephemeral" pages or as "persistent" pages. In either case, the pages +are not directly addressible by the guest, only copied to and fro via +the tmem interface. Ephemeral pages are a nice place for a guest to +put recently evicted clean pages that it might need again; these pages +can be reclaimed synchronously by Xen for other guests or other uses. +Persistent pages are a nice place for a guest to put "swap" pages to +avoid sending them to disk. These pages retain data as long as the +guest lives, but count against the guest memory allocation. + +This patch contains the Linux paravirtualization changes to +complement the tmem Xen patch (xen-unstable c/s 19646). It +implements "precache" (ext3 only as of now), "preswap", +and limited "shared precache" (ocfs2 only as of now) support. +CONFIG options are required to turn on +the support (but in this patch they default to "y"). If +the underlying Xen does not have tmem support or has it +turned off, this is sensed early to avoid nearly all +hypercalls. + +Lots of useful prose about tmem can be found at +http://oss.oracle.com/projects/tmem + +Signed-off-by: Dan Magenheimer +Acked-by: jbeulich@novell.com + +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-29/Documentation/transcendent-memory.txt 2009-12-29 16:15:01.000000000 +0100 +@@ -0,0 +1,176 @@ ++Normal memory is directly addressable by the kernel, of a known ++normally-fixed size, synchronously accessible, and persistent (though ++not across a reboot). ++ ++What if there was a class of memory that is of unknown and dynamically ++variable size, is addressable only indirectly by the kernel, can be ++configured either as persistent or as "ephemeral" (meaning it will be ++around for awhile, but might disappear without warning), and is still ++fast enough to be synchronously accessible? ++ ++We call this latter class "transcendent memory" and it provides an ++interesting opportunity to more efficiently utilize RAM in a virtualized ++environment. However this "memory but not really memory" may also have ++applications in NON-virtualized environments, such as hotplug-memory ++deletion, SSDs, and page cache compression. Others have suggested ideas ++such as allowing use of highmem memory without a highmem kernel, or use ++of spare video memory. ++ ++Transcendent memory, or "tmem" for short, provides a well-defined API to ++access this unusual class of memory. (A summary of the API is provided ++below.) The basic operations are page-copy-based and use a flexible ++object-oriented addressing mechanism. Tmem assumes that some "privileged ++entity" is capable of executing tmem requests and storing pages of data; ++this entity is currently a hypervisor and operations are performed via ++hypercalls, but the entity could be a kernel policy, or perhaps a ++"memory node" in a cluster of blades connected by a high-speed ++interconnect such as hypertransport or QPI. ++ ++Since tmem is not directly accessible and because page copying is done ++to/from physical pageframes, it more suitable for in-kernel memory needs ++than for userland applications. However, there may be yet undiscovered ++userland possibilities. ++ ++With the tmem concept outlined vaguely and its broader potential hinted, ++we will overview two existing examples of how tmem can be used by the ++kernel. ++ ++"Cleancache" can be thought of as a page-granularity victim cache for clean ++pages that the kernel's pageframe replacement algorithm (PFRA) would like ++to keep around, but can't since there isn't enough memory. So when the ++PFRA "evicts" a page, it first puts it into the cleancache via a call to ++tmem. And any time a filesystem reads a page from disk, it first attempts ++to get the page from cleancache. If it's there, a disk access is eliminated. ++If not, the filesystem just goes to the disk like normal. Cleancache is ++"ephemeral" so whether a page is kept in cleancache (between the "put" and ++the "get") is dependent on a number of factors that are invisible to ++the kernel. ++ ++"Frontswap" is so named because it can be thought of as the opposite of ++a "backing store". Frontswap IS persistent, but for various reasons may not ++always be available for use, again due to factors that may not be visible to ++the kernel. (But, briefly, if the kernel is being "good" and has shared its ++resources nicely, then it will be able to use frontswap, else it will not.) ++Once a page is put, a get on the page will always succeed. So when the ++kernel finds itself in a situation where it needs to swap out a page, it ++first attempts to use frontswap. If the put works, a disk write and ++(usually) a disk read are avoided. If it doesn't, the page is written ++to swap as usual. Unlike cleancache, whether a page is stored in frontswap ++vs swap is recorded in kernel data structures, so when a page needs to ++be fetched, the kernel does a get if it is in frontswap and reads from ++swap if it is not in frontswap. ++ ++Both cleancache and frontswap may be optionally compressed, trading off 2x ++space reduction vs 10x performance for access. Cleancache also has a ++sharing feature, which allows different nodes in a "virtual cluster" ++to share a local page cache. ++ ++Tmem has some similarity to IBM's Collaborative Memory Management, but ++creates more of a partnership between the kernel and the "privileged ++entity" and is not very invasive. Tmem may be applicable for KVM and ++containers; there is some disagreement on the extent of its value. ++Tmem is highly complementary to ballooning (aka page granularity hot ++plug) and memory deduplication (aka transparent content-based page ++sharing) but still has value when neither are present. ++ ++Performance is difficult to quantify because some benchmarks respond ++very favorably to increases in memory and tmem may do quite well on ++those, depending on how much tmem is available which may vary widely ++and dynamically, depending on conditions completely outside of the ++system being measured. Ideas on how best to provide useful metrics ++would be appreciated. ++ ++Tmem is supported starting in Xen 4.0 and is in Xen's Linux 2.6.18-xen ++source tree. It is also released as a technology preview in Oracle's ++Xen-based virtualization product, Oracle VM 2.2. Again, Xen is not ++necessarily a requirement, but currently provides the only existing ++implementation of tmem. ++ ++Lots more information about tmem can be found at: ++ http://oss.oracle.com/projects/tmem ++and there was a talk about it on the first day of Linux Symposium in ++July 2009; an updated talk is planned at linux.conf.au in January 2010. ++Tmem is the result of a group effort, including Dan Magenheimer, ++Chris Mason, Dave McCracken, Kurt Hackel and Zhigang Wang, with helpful ++input from Jeremy Fitzhardinge, Keir Fraser, Ian Pratt, Sunil Mushran, ++Joel Becker, and Jan Beulich. ++ ++THE TRANSCENDENT MEMORY API ++ ++Transcendent memory is made up of a set of pools. Each pool is made ++up of a set of objects. And each object contains a set of pages. ++The combination of a 32-bit pool id, a 64-bit object id, and a 32-bit ++page id, uniquely identify a page of tmem data, and this tuple is called ++a "handle." Commonly, the three parts of a handle are used to address ++a filesystem, a file within that filesystem, and a page within that file; ++however an OS can use any values as long as they uniquely identify ++a page of data. ++ ++When a tmem pool is created, it is given certain attributes: It can ++be private or shared, and it can be persistent or ephemeral. Each ++combination of these attributes provides a different set of useful ++functionality and also defines a slightly different set of semantics ++for the various operations on the pool. Other pool attributes include ++the size of the page and a version number. ++ ++Once a pool is created, operations are performed on the pool. Pages ++are copied between the OS and tmem and are addressed using a handle. ++Pages and/or objects may also be flushed from the pool. When all ++operations are completed, a pool can be destroyed. ++ ++The specific tmem functions are called in Linux through a set of ++accessor functions: ++ ++int (*new_pool)(struct tmem_pool_uuid uuid, u32 flags); ++int (*destroy_pool)(u32 pool_id); ++int (*put_page)(u32 pool_id, u64 object, u32 index, unsigned long pfn); ++int (*get_page)(u32 pool_id, u64 object, u32 index, unsigned long pfn); ++int (*flush_page)(u32 pool_id, u64 object, u32 index); ++int (*flush_object)(u32 pool_id, u64 object); ++ ++The new_pool accessor creates a new pool and returns a pool id ++which is a non-negative 32-bit integer. If the flags parameter ++specifies that the pool is to be shared, the uuid is a 128-bit "shared ++secret" else it is ignored. The destroy_pool accessor destroys the pool. ++(Note: shared pools are not supported until security implications ++are better understood.) ++ ++The put_page accessor copies a page of data from the specified pageframe ++and associates it with the specified handle. ++ ++The get_page accessor looks up a page of data in tmem associated with ++the specified handle and, if found, copies it to the specified pageframe. ++ ++The flush_page accessor ensures that subsequent gets of a page with ++the specified handle will fail. The flush_object accessor ensures ++that subsequent gets of any page matching the pool id and object ++will fail. ++ ++There are many subtle but critical behaviors for get_page and put_page: ++- Any put_page (with one notable exception) may be rejected and the client ++ must be prepared to deal with that failure. A put_page copies, NOT moves, ++ data; that is the data exists in both places. Linux is responsible for ++ destroying or overwriting its own copy, or alternately managing any ++ coherency between the copies. ++- Every page successfully put to a persistent pool must be found by a ++ subsequent get_page that specifies the same handle. A page successfully ++ put to an ephemeral pool has an indeterminate lifetime and even an ++ immediately subsequent get_page may fail. ++- A get_page to a private pool is destructive, that is it behaves as if ++ the get_page were atomically followed by a flush_page. A get_page ++ to a shared pool is non-destructive. A flush_page behaves just like ++ a get_page to a private pool except the data is thrown away. ++- Put-put-get coherency is guaranteed. For example, after the sequence: ++ put_page(ABC,D1); ++ put_page(ABC,D2); ++ get_page(ABC,E) ++ E may never contain the data from D1. However, even for a persistent ++ pool, the get_page may fail if the second put_page indicates failure. ++- Get-get coherency is guaranteed. For example, in the sequence: ++ put_page(ABC,D); ++ get_page(ABC,E1); ++ get_page(ABC,E2) ++ if the first get_page fails, the second must also fail. ++- A tmem implementation provides no serialization guarantees (e.g. to ++ an SMP Linux). So if different Linux threads are putting and flushing ++ the same page, the results are indeterminate. +--- sle11sp1-2010-03-29.orig/fs/btrfs/extent_io.c 2010-03-29 09:00:36.000000000 +0200 ++++ sle11sp1-2010-03-29/fs/btrfs/extent_io.c 2009-12-17 23:28:33.000000000 +0100 +@@ -11,6 +11,7 @@ + #include + #include + #include ++#include + #include "extent_io.h" + #include "extent_map.h" + #include "compat.h" +@@ -2015,6 +2016,13 @@ static int __extent_read_full_page(struc + + set_page_extent_mapped(page); + ++ if (!PageUptodate(page)) { ++ if (precache_get(page->mapping, page->index, page) == 1) { ++ BUG_ON(blocksize != PAGE_SIZE); ++ goto out; ++ } ++ } ++ + end = page_end; + lock_extent(tree, start, end, GFP_NOFS); + +@@ -2131,6 +2139,7 @@ static int __extent_read_full_page(struc + cur = cur + iosize; + page_offset += iosize; + } ++out: + if (!nr) { + if (!PageError(page)) + SetPageUptodate(page); +--- sle11sp1-2010-03-29.orig/fs/btrfs/super.c 2010-03-29 09:00:36.000000000 +0200 ++++ sle11sp1-2010-03-29/fs/btrfs/super.c 2009-12-17 21:50:16.000000000 +0100 +@@ -38,6 +38,7 @@ + #include + #include + #include ++#include + #include "compat.h" + #include "ctree.h" + #include "disk-io.h" +@@ -387,6 +388,7 @@ static int btrfs_fill_super(struct super + sb->s_root = root_dentry; + + save_mount_options(sb, data); ++ precache_init(sb); + return 0; + + fail_close: +--- sle11sp1-2010-03-29.orig/fs/buffer.c 2010-03-29 09:00:36.000000000 +0200 ++++ sle11sp1-2010-03-29/fs/buffer.c 2010-03-01 14:15:58.000000000 +0100 +@@ -41,6 +41,7 @@ + #include + #include + #include ++#include + + static int fsync_buffers_list(spinlock_t *lock, struct list_head *list); + +@@ -276,6 +277,11 @@ void invalidate_bdev(struct block_device + + invalidate_bh_lrus(); + invalidate_mapping_pages(mapping, 0, -1); ++ ++ /* 99% of the time, we don't need to flush the precache on the bdev. ++ * But, for the strange corners, lets be cautious ++ */ ++ precache_flush_inode(mapping); + } + EXPORT_SYMBOL(invalidate_bdev); + +--- sle11sp1-2010-03-29.orig/fs/ext3/super.c 2010-03-29 09:00:36.000000000 +0200 ++++ sle11sp1-2010-03-29/fs/ext3/super.c 2009-12-04 10:29:25.000000000 +0100 +@@ -38,6 +38,7 @@ + #include + #include + #include ++#include + + #include + +@@ -1334,6 +1335,7 @@ static int ext3_setup_super(struct super + } else { + printk("internal journal\n"); + } ++ precache_init(sb); + return res; + } + +--- sle11sp1-2010-03-29.orig/fs/ext4/super.c 2010-03-29 09:00:36.000000000 +0200 ++++ sle11sp1-2010-03-29/fs/ext4/super.c 2010-01-07 09:36:31.000000000 +0100 +@@ -39,6 +39,7 @@ + #include + #include + #include ++#include + #include + + #include "ext4.h" +@@ -1685,6 +1686,8 @@ static int ext4_setup_super(struct super + EXT4_INODES_PER_GROUP(sb), + sbi->s_mount_opt); + ++ precache_init(sb); ++ + return res; + } + +--- sle11sp1-2010-03-29.orig/fs/mpage.c 2010-03-29 09:00:36.000000000 +0200 ++++ sle11sp1-2010-03-29/fs/mpage.c 2009-12-04 10:29:25.000000000 +0100 +@@ -26,6 +26,7 @@ + #include + #include + #include ++#include + + /* + * I/O completion handler for multipage BIOs. +@@ -285,6 +286,13 @@ do_mpage_readpage(struct bio *bio, struc + SetPageMappedToDisk(page); + } + ++ if (fully_mapped && ++ blocks_per_page == 1 && !PageUptodate(page) && ++ precache_get(page->mapping, page->index, page) == 1) { ++ SetPageUptodate(page); ++ goto confused; ++ } ++ + /* + * This page will go to BIO. Do we need to send this BIO off first? + */ +--- sle11sp1-2010-03-29.orig/fs/ocfs2/super.c 2010-03-29 09:00:36.000000000 +0200 ++++ sle11sp1-2010-03-29/fs/ocfs2/super.c 2010-03-29 09:02:16.000000000 +0200 +@@ -41,6 +41,7 @@ + #include + #include + #include ++#include + #include + + #define MLOG_MASK_PREFIX ML_SUPER +@@ -2260,6 +2261,7 @@ static int ocfs2_initialize_super(struct + mlog_errno(status); + goto bail; + } ++ shared_precache_init(sb, &di->id2.i_super.s_uuid[0]); + + bail: + mlog_exit(status); +--- sle11sp1-2010-03-29.orig/fs/super.c 2010-03-29 09:00:36.000000000 +0200 ++++ sle11sp1-2010-03-29/fs/super.c 2010-02-17 14:34:10.000000000 +0100 +@@ -37,6 +37,7 @@ + #include + #include + #include ++#include + #include + #include "internal.h" + +@@ -104,6 +105,9 @@ static struct super_block *alloc_super(s + s->s_qcop = sb_quotactl_ops; + s->s_op = &default_op; + s->s_time_gran = 1000000000; ++#ifdef CONFIG_PRECACHE ++ s->precache_poolid = -1; ++#endif + } + out: + return s; +@@ -194,6 +198,7 @@ void deactivate_super(struct super_block + vfs_dq_off(s, 0); + down_write(&s->s_umount); + fs->kill_sb(s); ++ precache_flush_filesystem(s); + put_filesystem(fs); + put_super(s); + } +@@ -220,6 +225,7 @@ void deactivate_locked_super(struct supe + spin_unlock(&sb_lock); + vfs_dq_off(s, 0); + fs->kill_sb(s); ++ precache_flush_filesystem(s); + put_filesystem(fs); + put_super(s); + } else { +--- sle11sp1-2010-03-29.orig/include/linux/fs.h 2010-03-29 09:00:36.000000000 +0200 ++++ sle11sp1-2010-03-29/include/linux/fs.h 2010-03-22 12:11:50.000000000 +0100 +@@ -1384,6 +1384,9 @@ struct super_block { + /* Granularity of c/m/atime in ns. + Cannot be worse than a second */ + u32 s_time_gran; ++#ifdef CONFIG_PRECACHE ++ u32 precache_poolid; ++#endif + + /* + * Filesystem subtype. If non-empty the filesystem type field +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-29/include/linux/precache.h 2009-12-04 10:29:25.000000000 +0100 +@@ -0,0 +1,55 @@ ++#ifndef _LINUX_PRECACHE_H ++ ++#include ++#include ++ ++#ifdef CONFIG_PRECACHE ++extern void precache_init(struct super_block *sb); ++extern void shared_precache_init(struct super_block *sb, char *uuid); ++extern int precache_get(struct address_space *mapping, unsigned long index, ++ struct page *empty_page); ++extern int precache_put(struct address_space *mapping, unsigned long index, ++ struct page *page); ++extern int precache_flush(struct address_space *mapping, unsigned long index); ++extern int precache_flush_inode(struct address_space *mapping); ++extern int precache_flush_filesystem(struct super_block *s); ++#else ++static inline void precache_init(struct super_block *sb) ++{ ++} ++ ++static inline void shared_precache_init(struct super_block *sb, char *uuid) ++{ ++} ++ ++static inline int precache_get(struct address_space *mapping, ++ unsigned long index, struct page *empty_page) ++{ ++ return 0; ++} ++ ++static inline int precache_put(struct address_space *mapping, ++ unsigned long index, struct page *page) ++{ ++ return 0; ++} ++ ++static inline int precache_flush(struct address_space *mapping, ++ unsigned long index) ++{ ++ return 0; ++} ++ ++static inline int precache_flush_inode(struct address_space *mapping) ++{ ++ return 0; ++} ++ ++static inline int precache_flush_filesystem(struct super_block *s) ++{ ++ return 0; ++} ++#endif ++ ++#define _LINUX_PRECACHE_H ++#endif /* _LINUX_PRECACHE_H */ +--- sle11sp1-2010-03-29.orig/include/linux/swap.h 2010-03-29 09:00:36.000000000 +0200 ++++ sle11sp1-2010-03-29/include/linux/swap.h 2009-12-04 10:29:25.000000000 +0100 +@@ -178,8 +178,59 @@ struct swap_info_struct { + unsigned int max; + unsigned int inuse_pages; + unsigned int old_block_size; ++#ifdef CONFIG_PRESWAP ++ unsigned long *preswap_map; ++ unsigned int preswap_pages; ++#endif + }; + ++#ifdef CONFIG_PRESWAP ++ ++#include ++extern int preswap_sysctl_handler(struct ctl_table *, int, void __user *, ++ size_t *, loff_t *); ++extern const unsigned long preswap_zero, preswap_infinity; ++ ++extern void preswap_shrink(unsigned long); ++extern int preswap_test(struct swap_info_struct *, unsigned long); ++extern void preswap_init(unsigned); ++extern int preswap_put(struct page *); ++extern int preswap_get(struct page *); ++extern void preswap_flush(unsigned, unsigned long); ++extern void preswap_flush_area(unsigned); ++#else ++static inline void preswap_shrink(unsigned long target_pages) ++{ ++} ++ ++static inline int preswap_test(struct swap_info_struct *sis, unsigned long offset) ++{ ++ return 0; ++} ++ ++static inline void preswap_init(unsigned type) ++{ ++} ++ ++static inline int preswap_put(struct page *page) ++{ ++ return 0; ++} ++ ++static inline int preswap_get(struct page *get) ++{ ++ return 0; ++} ++ ++static inline void preswap_flush(unsigned type, unsigned long offset) ++{ ++} ++ ++static inline void preswap_flush_area(unsigned type) ++{ ++} ++#endif /* CONFIG_PRESWAP */ ++ + struct swap_list_t { + int head; /* head of priority-ordered swapfile list */ + int next; /* swapfile to be used next */ +--- sle11sp1-2010-03-29.orig/kernel/sysctl.c 2010-03-29 09:00:36.000000000 +0200 ++++ sle11sp1-2010-03-29/kernel/sysctl.c 2010-03-22 12:11:55.000000000 +0100 +@@ -1452,6 +1452,18 @@ static struct ctl_table vm_table[] = { + .mode = 0644, + .proc_handler = &proc_dointvec, + }, ++#ifdef CONFIG_PRESWAP ++ { ++ .ctl_name = CTL_UNNUMBERED, ++ .procname = "preswap", ++ .data = NULL, ++ .maxlen = sizeof(unsigned long), ++ .mode = 0644, ++ .proc_handler = &preswap_sysctl_handler, ++ .extra1 = (void *)&preswap_zero, ++ .extra2 = (void *)&preswap_infinity, ++ }, ++#endif + #ifdef CONFIG_MEMORY_FAILURE + { + .ctl_name = CTL_UNNUMBERED, +--- sle11sp1-2010-03-29.orig/mm/Kconfig 2010-03-29 09:00:36.000000000 +0200 ++++ sle11sp1-2010-03-29/mm/Kconfig 2010-02-17 14:33:13.000000000 +0100 +@@ -289,3 +289,31 @@ config NOMMU_INITIAL_TRIM_EXCESS + of 1 says that all excess pages should be trimmed. + + See Documentation/nommu-mmap.txt for more information. ++ ++# ++# support for transcendent memory ++# ++config TMEM ++ bool ++ help ++ In a virtualized environment, allows unused and underutilized ++ system physical memory to be made accessible through a narrow ++ well-defined page-copy-based API. If unsure, say Y. ++ ++config PRECACHE ++ bool "Cache clean pages in transcendent memory" ++ depends on XEN ++ select TMEM ++ help ++ Allows the transcendent memory pool to be used to store clean ++ page-cache pages which, under some circumstances, will greatly ++ reduce paging and thus improve performance. If unsure, say Y. ++ ++config PRESWAP ++ bool "Swap pages to transcendent memory" ++ depends on XEN ++ select TMEM ++ help ++ Allows the transcendent memory pool to be used as a pseudo-swap ++ device which, under some circumstances, will greatly reduce ++ swapping and thus improve performance. If unsure, say Y. +--- sle11sp1-2010-03-29.orig/mm/Makefile 2010-03-29 09:00:36.000000000 +0200 ++++ sle11sp1-2010-03-29/mm/Makefile 2009-12-04 10:29:25.000000000 +0100 +@@ -17,6 +17,9 @@ obj-y += init-mm.o + + obj-$(CONFIG_BOUNCE) += bounce.o + obj-$(CONFIG_SWAP) += page_io.o swap_state.o swapfile.o thrash.o ++obj-$(CONFIG_TMEM) += tmem.o ++obj-$(CONFIG_PRESWAP) += preswap.o ++obj-$(CONFIG_PRECACHE) += precache.o + obj-$(CONFIG_HAS_DMA) += dmapool.o + obj-$(CONFIG_HUGETLBFS) += hugetlb.o + obj-$(CONFIG_NUMA) += mempolicy.o +--- sle11sp1-2010-03-29.orig/mm/filemap.c 2010-03-29 09:00:36.000000000 +0200 ++++ sle11sp1-2010-03-29/mm/filemap.c 2010-03-01 14:16:13.000000000 +0100 +@@ -33,6 +33,7 @@ + #include + #include /* for BUG_ON(!in_atomic()) only */ + #include ++#include + #include /* for page_is_file_cache() */ + #include "internal.h" + +@@ -119,6 +120,16 @@ void __remove_from_page_cache(struct pag + { + struct address_space *mapping = page->mapping; + ++ /* ++ * if we're uptodate, flush out into the precache, otherwise ++ * invalidate any existing precache entries. We can't leave ++ * stale data around in the precache once our page is gone ++ */ ++ if (PageUptodate(page)) ++ precache_put(page->mapping, page->index, page); ++ else ++ precache_flush(page->mapping, page->index); ++ + radix_tree_delete(&mapping->page_tree, page->index); + page->mapping = NULL; + mapping->nrpages--; +--- sle11sp1-2010-03-29.orig/mm/page_io.c 2010-03-29 09:00:36.000000000 +0200 ++++ sle11sp1-2010-03-29/mm/page_io.c 2010-02-17 14:40:38.000000000 +0100 +@@ -115,6 +115,13 @@ int swap_writepage(struct page *page, st + return ret; + } + ++ if (preswap_put(page) == 1) { ++ set_page_writeback(page); ++ unlock_page(page); ++ end_page_writeback(page); ++ goto out; ++ } ++ + bio = get_swap_bio(GFP_NOIO, page_private(page), page, + end_swap_bio_write); + if (bio == NULL) { +@@ -184,6 +191,12 @@ int swap_readpage(struct page *page) + return ret; + } + ++ if (preswap_get(page) == 1) { ++ SetPageUptodate(page); ++ unlock_page(page); ++ goto out; ++ } ++ + bio = get_swap_bio(GFP_KERNEL, page_private(page), page, + end_swap_bio_read); + if (bio == NULL) { +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-29/mm/precache.c 2009-12-04 10:29:25.000000000 +0100 +@@ -0,0 +1,140 @@ ++/* ++ * linux/mm/precache.c ++ * ++ * Implements "precache" for filesystems/pagecache on top of transcendent ++ * memory ("tmem") API. A filesystem creates an "ephemeral tmem pool" ++ * and retains the returned pool_id in its superblock. Clean pages evicted ++ * from pagecache may be "put" into the pool and associated with a "handle" ++ * consisting of the pool_id, an object (inode) id, and an index (page offset). ++ * Note that the page is copied to tmem; no kernel mappings are changed. ++ * If the page is later needed, the filesystem (or VFS) issues a "get", passing ++ * the same handle and an empty pageframe. If successful, the page is copied ++ * into the pageframe and a disk read is avoided. But since the tmem pool ++ * is of indeterminate size, a "put" page has indeterminate longevity ++ * ("ephemeral"), and the "get" may fail, in which case the filesystem must ++ * read the page from disk as before. Note that the filesystem/pagecache are ++ * responsible for maintaining coherency between the pagecache, precache, ++ * and the disk, for which "flush page" and "flush object" actions are ++ * provided. And when a filesystem is unmounted, it must "destroy" the pool. ++ * ++ * Two types of pools may be created for a precache: "private" or "shared". ++ * For a private pool, a successful "get" always flushes, implementing ++ * exclusive semantics; for a "shared" pool (which is intended for use by ++ * co-resident nodes of a cluster filesystem), the "flush" is not guaranteed. ++ * In either case, a failed "duplicate" put (overwrite) always guarantee ++ * the old data is flushed. ++ * ++ * Note also that multiple accesses to a tmem pool may be concurrent and any ++ * ordering must be guaranteed by the caller. ++ * ++ * Copyright (C) 2008,2009 Dan Magenheimer, Oracle Corp. ++ */ ++ ++#include ++#include ++#include "tmem.h" ++ ++static int precache_auto_allocate; /* set to 1 to auto_allocate */ ++ ++int precache_put(struct address_space *mapping, unsigned long index, ++ struct page *page) ++{ ++ u32 tmem_pool = mapping->host->i_sb->precache_poolid; ++ u64 obj = (unsigned long) mapping->host->i_ino; ++ u32 ind = (u32) index; ++ unsigned long mfn = pfn_to_mfn(page_to_pfn(page)); ++ int ret; ++ ++ if ((s32)tmem_pool < 0) { ++ if (!precache_auto_allocate) ++ return 0; ++ /* a put on a non-existent precache may auto-allocate one */ ++ ret = tmem_new_pool(0, 0, 0); ++ if (ret < 0) ++ return 0; ++ printk(KERN_INFO ++ "Mapping superblock for s_id=%s to precache_id=%d\n", ++ mapping->host->i_sb->s_id, tmem_pool); ++ mapping->host->i_sb->precache_poolid = tmem_pool; ++ } ++ if (ind != index) ++ return 0; ++ mb(); /* ensure page is quiescent; tmem may address it with an alias */ ++ return tmem_put_page(tmem_pool, obj, ind, mfn); ++} ++ ++int precache_get(struct address_space *mapping, unsigned long index, ++ struct page *empty_page) ++{ ++ u32 tmem_pool = mapping->host->i_sb->precache_poolid; ++ u64 obj = (unsigned long) mapping->host->i_ino; ++ u32 ind = (u32) index; ++ unsigned long mfn = pfn_to_mfn(page_to_pfn(empty_page)); ++ ++ if ((s32)tmem_pool < 0) ++ return 0; ++ if (ind != index) ++ return 0; ++ ++ return tmem_get_page(tmem_pool, obj, ind, mfn); ++} ++EXPORT_SYMBOL(precache_get); ++ ++int precache_flush(struct address_space *mapping, unsigned long index) ++{ ++ u32 tmem_pool = mapping->host->i_sb->precache_poolid; ++ u64 obj = (unsigned long) mapping->host->i_ino; ++ u32 ind = (u32) index; ++ ++ if ((s32)tmem_pool < 0) ++ return 0; ++ if (ind != index) ++ return 0; ++ ++ return tmem_flush_page(tmem_pool, obj, ind); ++} ++EXPORT_SYMBOL(precache_flush); ++ ++int precache_flush_inode(struct address_space *mapping) ++{ ++ u32 tmem_pool = mapping->host->i_sb->precache_poolid; ++ u64 obj = (unsigned long) mapping->host->i_ino; ++ ++ if ((s32)tmem_pool < 0) ++ return 0; ++ ++ return tmem_flush_object(tmem_pool, obj); ++} ++EXPORT_SYMBOL(precache_flush_inode); ++ ++int precache_flush_filesystem(struct super_block *sb) ++{ ++ u32 tmem_pool = sb->precache_poolid; ++ int ret; ++ ++ if ((s32)tmem_pool < 0) ++ return 0; ++ ret = tmem_destroy_pool(tmem_pool); ++ if (!ret) ++ return 0; ++ printk(KERN_INFO ++ "Unmapping superblock for s_id=%s from precache_id=%d\n", ++ sb->s_id, ret); ++ sb->precache_poolid = 0; ++ return 1; ++} ++EXPORT_SYMBOL(precache_flush_filesystem); ++ ++void precache_init(struct super_block *sb) ++{ ++ sb->precache_poolid = tmem_new_pool(0, 0, 0); ++} ++EXPORT_SYMBOL(precache_init); ++ ++void shared_precache_init(struct super_block *sb, char *uuid) ++{ ++ u64 uuid_lo = *(u64 *)uuid; ++ u64 uuid_hi = *(u64 *)(&uuid[8]); ++ sb->precache_poolid = tmem_new_pool(uuid_lo, uuid_hi, TMEM_POOL_SHARED); ++} ++EXPORT_SYMBOL(shared_precache_init); +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-29/mm/preswap.c 2009-12-04 10:29:25.000000000 +0100 +@@ -0,0 +1,182 @@ ++/* ++ * linux/mm/preswap.c ++ * ++ * Implements a fast "preswap" on top of the transcendent memory ("tmem") API. ++ * When a swapdisk is enabled (with swapon), a "private persistent tmem pool" ++ * is created along with a bit-per-page preswap_map. When swapping occurs ++ * and a page is about to be written to disk, a "put" into the pool may first ++ * be attempted by passing the pageframe to be swapped, along with a "handle" ++ * consisting of a pool_id, an object id, and an index. Since the pool is of ++ * indeterminate size, the "put" may be rejected, in which case the page ++ * is swapped to disk as normal. If the "put" is successful, the page is ++ * copied to tmem and the preswap_map records the success. Later, when ++ * the page needs to be swapped in, the preswap_map is checked and, if set, ++ * the page may be obtained with a "get" operation. Note that the swap ++ * subsystem is responsible for: maintaining coherency between the swapcache, ++ * preswap, and the swapdisk; for evicting stale pages from preswap; and for ++ * emptying preswap when swapoff is performed. The "flush page" and "flush ++ * object" actions are provided for this. ++ * ++ * Note that if a "duplicate put" is performed to overwrite a page and ++ * the "put" operation fails, the page (and old data) is flushed and lost. ++ * Also note that multiple accesses to a tmem pool may be concurrent and ++ * any ordering must be guaranteed by the caller. ++ * ++ * Copyright (C) 2008,2009 Dan Magenheimer, Oracle Corp. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "tmem.h" ++ ++static u32 preswap_poolid = -1; /* if negative, preswap will never call tmem */ ++ ++const unsigned long preswap_zero = 0, preswap_infinity = ~0UL; /* for sysctl */ ++ ++/* ++ * Swizzling increases objects per swaptype, increasing tmem concurrency ++ * for heavy swaploads. Later, larger nr_cpus -> larger SWIZ_BITS ++ */ ++#define SWIZ_BITS 4 ++#define SWIZ_MASK ((1 << SWIZ_BITS) - 1) ++#define oswiz(_type, _ind) ((_type << SWIZ_BITS) | (_ind & SWIZ_MASK)) ++#define iswiz(_ind) (_ind >> SWIZ_BITS) ++ ++/* ++ * preswap_map test/set/clear operations (must be atomic) ++ */ ++ ++int preswap_test(struct swap_info_struct *sis, unsigned long offset) ++{ ++ if (!sis->preswap_map) ++ return 0; ++ return test_bit(offset % BITS_PER_LONG, ++ &sis->preswap_map[offset/BITS_PER_LONG]); ++} ++ ++static inline void preswap_set(struct swap_info_struct *sis, ++ unsigned long offset) ++{ ++ if (!sis->preswap_map) ++ return; ++ set_bit(offset % BITS_PER_LONG, ++ &sis->preswap_map[offset/BITS_PER_LONG]); ++} ++ ++static inline void preswap_clear(struct swap_info_struct *sis, ++ unsigned long offset) ++{ ++ if (!sis->preswap_map) ++ return; ++ clear_bit(offset % BITS_PER_LONG, ++ &sis->preswap_map[offset/BITS_PER_LONG]); ++} ++ ++/* ++ * preswap tmem operations ++ */ ++ ++/* returns 1 if the page was successfully put into preswap, 0 if the page ++ * was declined, and -ERRNO for a specific error */ ++int preswap_put(struct page *page) ++{ ++ swp_entry_t entry = { .val = page_private(page), }; ++ unsigned type = swp_type(entry); ++ pgoff_t offset = swp_offset(entry); ++ u64 ind64 = (u64)offset; ++ u32 ind = (u32)offset; ++ unsigned long mfn = pfn_to_mfn(page_to_pfn(page)); ++ struct swap_info_struct *sis = get_swap_info_struct(type); ++ int dup = 0, ret; ++ ++ if ((s32)preswap_poolid < 0) ++ return 0; ++ if (ind64 != ind) ++ return 0; ++ if (preswap_test(sis, offset)) ++ dup = 1; ++ mb(); /* ensure page is quiescent; tmem may address it with an alias */ ++ ret = tmem_put_page(preswap_poolid, oswiz(type, ind), iswiz(ind), mfn); ++ if (ret == 1) { ++ preswap_set(sis, offset); ++ if (!dup) ++ sis->preswap_pages++; ++ } else if (dup) { ++ /* failed dup put always results in an automatic flush of ++ * the (older) page from preswap */ ++ preswap_clear(sis, offset); ++ sis->preswap_pages--; ++ } ++ return ret; ++} ++ ++/* returns 1 if the page was successfully gotten from preswap, 0 if the page ++ * was not present (should never happen!), and -ERRNO for a specific error */ ++int preswap_get(struct page *page) ++{ ++ swp_entry_t entry = { .val = page_private(page), }; ++ unsigned type = swp_type(entry); ++ pgoff_t offset = swp_offset(entry); ++ u64 ind64 = (u64)offset; ++ u32 ind = (u32)offset; ++ unsigned long mfn = pfn_to_mfn(page_to_pfn(page)); ++ struct swap_info_struct *sis = get_swap_info_struct(type); ++ int ret; ++ ++ if ((s32)preswap_poolid < 0) ++ return 0; ++ if (ind64 != ind) ++ return 0; ++ if (!preswap_test(sis, offset)) ++ return 0; ++ ret = tmem_get_page(preswap_poolid, oswiz(type, ind), iswiz(ind), mfn); ++ return ret; ++} ++ ++/* flush a single page from preswap */ ++void preswap_flush(unsigned type, unsigned long offset) ++{ ++ u64 ind64 = (u64)offset; ++ u32 ind = (u32)offset; ++ struct swap_info_struct *sis = get_swap_info_struct(type); ++ int ret = 1; ++ ++ if ((s32)preswap_poolid < 0) ++ return; ++ if (ind64 != ind) ++ return; ++ if (preswap_test(sis, offset)) { ++ ret = tmem_flush_page(preswap_poolid, ++ oswiz(type, ind), iswiz(ind)); ++ sis->preswap_pages--; ++ preswap_clear(sis, offset); ++ } ++} ++ ++/* flush all pages from the passed swaptype */ ++void preswap_flush_area(unsigned type) ++{ ++ struct swap_info_struct *sis = get_swap_info_struct(type); ++ int ind; ++ ++ if ((s32)preswap_poolid < 0) ++ return; ++ for (ind = SWIZ_MASK; ind >= 0; ind--) ++ (void)tmem_flush_object(preswap_poolid, oswiz(type, ind)); ++ sis->preswap_pages = 0; ++} ++ ++void preswap_init(unsigned type) ++{ ++ /* only need one tmem pool for all swap types */ ++ if ((s32)preswap_poolid >= 0) ++ return; ++ preswap_poolid = tmem_new_pool(0, 0, TMEM_POOL_PERSIST); ++} +--- sle11sp1-2010-03-29.orig/mm/swapfile.c 2010-03-29 09:00:36.000000000 +0200 ++++ sle11sp1-2010-03-29/mm/swapfile.c 2010-03-01 14:16:19.000000000 +0100 +@@ -589,6 +589,7 @@ static int swap_entry_free(struct swap_i + swap_list.next = p - swap_info; + nr_swap_pages++; + p->inuse_pages--; ++ preswap_flush(p - swap_info, offset); + } + if (!swap_count(count)) + mem_cgroup_uncharge_swap(ent); +@@ -988,7 +989,7 @@ static int unuse_mm(struct mm_struct *mm + * Recycle to start on reaching the end, returning 0 when empty. + */ + static unsigned int find_next_to_unuse(struct swap_info_struct *si, +- unsigned int prev) ++ unsigned int prev, unsigned int preswap) + { + unsigned int max = si->max; + unsigned int i = prev; +@@ -1014,6 +1015,12 @@ static unsigned int find_next_to_unuse(s + prev = 0; + i = 1; + } ++ if (preswap) { ++ if (preswap_test(si, i)) ++ break; ++ else ++ continue; ++ } + count = si->swap_map[i]; + if (count && swap_count(count) != SWAP_MAP_BAD) + break; +@@ -1025,8 +1032,12 @@ static unsigned int find_next_to_unuse(s + * We completely avoid races by reading each swap page in advance, + * and then search for the process using it. All the necessary + * page table adjustments can then be made atomically. ++ * ++ * if the boolean preswap is true, only unuse pages_to_unuse pages; ++ * pages_to_unuse==0 means all pages + */ +-static int try_to_unuse(unsigned int type) ++static int try_to_unuse(unsigned int type, unsigned int preswap, ++ unsigned long pages_to_unuse) + { + struct swap_info_struct * si = &swap_info[type]; + struct mm_struct *start_mm; +@@ -1062,7 +1073,7 @@ static int try_to_unuse(unsigned int typ + * one pass through swap_map is enough, but not necessarily: + * there are races when an instance of an entry might be missed. + */ +- while ((i = find_next_to_unuse(si, i)) != 0) { ++ while ((i = find_next_to_unuse(si, i, preswap)) != 0) { + if (signal_pending(current)) { + retval = -EINTR; + break; +@@ -1255,6 +1266,8 @@ retry: + * interactive performance. + */ + cond_resched(); ++ if (preswap && pages_to_unuse && !--pages_to_unuse) ++ break; + } + + mmput(start_mm); +@@ -1598,7 +1611,7 @@ SYSCALL_DEFINE1(swapoff, const char __us + spin_unlock(&swap_lock); + + current->flags |= PF_OOM_ORIGIN; +- err = try_to_unuse(type); ++ err = try_to_unuse(type, 0, 0); + current->flags &= ~PF_OOM_ORIGIN; + + if (err) { +@@ -1647,9 +1660,14 @@ SYSCALL_DEFINE1(swapoff, const char __us + swap_map = p->swap_map; + p->swap_map = NULL; + p->flags = 0; ++ preswap_flush_area(p - swap_info); + spin_unlock(&swap_lock); + mutex_unlock(&swapon_mutex); + vfree(swap_map); ++#ifdef CONFIG_PRESWAP ++ if (p->preswap_map) ++ vfree(p->preswap_map); ++#endif + /* Destroy swap account informatin */ + swap_cgroup_swapoff(type); + +@@ -1803,6 +1821,7 @@ SYSCALL_DEFINE2(swapon, const char __use + unsigned long maxpages = 1; + unsigned long swapfilepages; + unsigned short *swap_map = NULL; ++ unsigned long *preswap_map = NULL; + struct page *page = NULL; + struct inode *inode = NULL; + int did_down = 0; +@@ -1971,6 +1990,12 @@ SYSCALL_DEFINE2(swapon, const char __use + swap_map[page_nr] = SWAP_MAP_BAD; + } + ++#ifdef CONFIG_PRESWAP ++ preswap_map = vmalloc(maxpages / sizeof(long)); ++ if (preswap_map) ++ memset(preswap_map, 0, maxpages / sizeof(long)); ++#endif ++ + error = swap_cgroup_swapon(type, maxpages); + if (error) + goto bad_swap; +@@ -2013,6 +2038,9 @@ SYSCALL_DEFINE2(swapon, const char __use + else + p->prio = --least_priority; + p->swap_map = swap_map; ++#ifdef CONFIG_PRESWAP ++ p->preswap_map = preswap_map; ++#endif + p->flags |= SWP_WRITEOK; + nr_swap_pages += nr_good_pages; + total_swap_pages += nr_good_pages; +@@ -2038,6 +2066,7 @@ SYSCALL_DEFINE2(swapon, const char __use + } else { + swap_info[prev].next = p - swap_info; + } ++ preswap_init(p - swap_info); + spin_unlock(&swap_lock); + mutex_unlock(&swapon_mutex); + error = 0; +@@ -2054,6 +2083,7 @@ bad_swap_2: + p->swap_file = NULL; + p->flags = 0; + spin_unlock(&swap_lock); ++ vfree(preswap_map); + vfree(swap_map); + if (swap_file) + filp_close(swap_file, NULL); +@@ -2262,6 +2292,10 @@ int valid_swaphandles(swp_entry_t entry, + base++; + + spin_lock(&swap_lock); ++ if (preswap_test(si, target)) { ++ spin_unlock(&swap_lock); ++ return 0; ++ } + if (end > si->max) /* don't go beyond end of map */ + end = si->max; + +@@ -2272,6 +2306,9 @@ int valid_swaphandles(swp_entry_t entry, + break; + if (swap_count(si->swap_map[toff]) == SWAP_MAP_BAD) + break; ++ /* Don't read in preswap pages */ ++ if (preswap_test(si, toff)) ++ break; + } + /* Count contiguous allocated slots below our target */ + for (toff = target; --toff >= base; nr_pages++) { +@@ -2280,6 +2317,9 @@ int valid_swaphandles(swp_entry_t entry, + break; + if (swap_count(si->swap_map[toff]) == SWAP_MAP_BAD) + break; ++ /* Don't read in preswap pages */ ++ if (preswap_test(si, toff)) ++ break; + } + spin_unlock(&swap_lock); + +@@ -2290,3 +2330,92 @@ int valid_swaphandles(swp_entry_t entry, + *offset = ++toff; + return nr_pages? ++nr_pages: 0; + } ++ ++#ifdef CONFIG_PRESWAP ++/* ++ * preswap infrastructure functions ++ */ ++ ++/* code structure leveraged from sys_swapoff */ ++void preswap_shrink(unsigned long target_pages) ++{ ++ struct swap_info_struct *si = NULL; ++ unsigned long total_pages = 0, total_pages_to_unuse; ++ unsigned long pages = 0, unuse_pages = 0; ++ int type; ++ int wrapped = 0; ++ ++ do { ++ /* ++ * we don't want to hold swap_lock while doing a very ++ * lengthy try_to_unuse, but swap_list may change ++ * so restart scan from swap_list.head each time ++ */ ++ spin_lock(&swap_lock); ++ total_pages = 0; ++ for (type = swap_list.head; type >= 0; type = si->next) { ++ si = get_swap_info_struct(type); ++ total_pages += si->preswap_pages; ++ } ++ if (total_pages <= target_pages) { ++ spin_unlock(&swap_lock); ++ return; ++ } ++ total_pages_to_unuse = total_pages - target_pages; ++ for (type = swap_list.head; type >= 0; type = si->next) { ++ si = get_swap_info_struct(type); ++ if (total_pages_to_unuse < si->preswap_pages) ++ pages = unuse_pages = total_pages_to_unuse; ++ else { ++ pages = si->preswap_pages; ++ unuse_pages = 0; /* unuse all */ ++ } ++ if (security_vm_enough_memory_kern(pages)) ++ continue; ++ vm_unacct_memory(pages); ++ break; ++ } ++ spin_unlock(&swap_lock); ++ if (type < 0) ++ return; ++ current->flags |= PF_OOM_ORIGIN; ++ (void)try_to_unuse(type, 1, unuse_pages); ++ current->flags &= ~PF_OOM_ORIGIN; ++ wrapped++; ++ } while (wrapped <= 3); ++} ++ ++ ++#ifdef CONFIG_SYSCTL ++/* cat /sys/proc/vm/preswap provides total number of pages in preswap ++ * across all swaptypes. echo N > /sys/proc/vm/preswap attempts to shrink ++ * preswap page usage to N (usually 0) */ ++int preswap_sysctl_handler(ctl_table *table, int write, ++ void __user *buffer, size_t *length, loff_t *ppos) ++{ ++ unsigned long npages; ++ int type; ++ unsigned long totalpages = 0; ++ struct swap_info_struct *si = NULL; ++ ++ /* modeled after hugetlb_sysctl_handler in mm/hugetlb.c */ ++ if (!write) { ++ spin_lock(&swap_lock); ++ for (type = swap_list.head; type >= 0; type = si->next) { ++ si = get_swap_info_struct(type); ++ totalpages += si->preswap_pages; ++ } ++ spin_unlock(&swap_lock); ++ npages = totalpages; ++ } ++ table->data = &npages; ++ table->maxlen = sizeof(unsigned long); ++ proc_doulongvec_minmax(table, write, buffer, length, ppos); ++ ++ if (write) ++ preswap_shrink(npages); ++ ++ return 0; ++} ++#endif ++#endif /* CONFIG_PRESWAP */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-29/mm/tmem.h 2009-12-04 10:29:25.000000000 +0100 +@@ -0,0 +1,84 @@ ++/* ++ * linux/mm/tmem.h ++ * ++ * Interface to transcendent memory, used by mm/precache.c and mm/preswap.c ++ * Currently implemented on XEN, but may be implemented elsewhere in future. ++ * ++ * Copyright (C) 2008,2009 Dan Magenheimer, Oracle Corp. ++ */ ++ ++#ifdef CONFIG_XEN ++#include ++ ++/* Bits for HYPERVISOR_tmem_op(TMEM_NEW_POOL) */ ++#define TMEM_POOL_MIN_PAGESHIFT 12 ++#define TMEM_POOL_PAGEORDER (PAGE_SHIFT - TMEM_POOL_MIN_PAGESHIFT) ++ ++extern int xen_tmem_op(u32 tmem_cmd, u32 tmem_pool, u64 object, u32 index, ++ unsigned long gmfn, u32 tmem_offset, u32 pfn_offset, u32 len); ++extern int xen_tmem_new_pool(u32 tmem_cmd, u64 uuid_lo, u64 uuid_hi, u32 flags); ++ ++static inline int tmem_put_page(u32 pool_id, u64 object, u32 index, ++ unsigned long gmfn) ++{ ++ return xen_tmem_op(TMEM_PUT_PAGE, pool_id, object, index, ++ gmfn, 0, 0, 0); ++} ++ ++static inline int tmem_get_page(u32 pool_id, u64 object, u32 index, ++ unsigned long gmfn) ++{ ++ return xen_tmem_op(TMEM_GET_PAGE, pool_id, object, index, ++ gmfn, 0, 0, 0); ++} ++ ++static inline int tmem_flush_page(u32 pool_id, u64 object, u32 index) ++{ ++ return xen_tmem_op(TMEM_FLUSH_PAGE, pool_id, object, index, ++ 0, 0, 0, 0); ++} ++ ++static inline int tmem_flush_object(u32 pool_id, u64 object) ++{ ++ return xen_tmem_op(TMEM_FLUSH_OBJECT, pool_id, object, 0, 0, 0, 0, 0); ++} ++ ++static inline int tmem_new_pool(u64 uuid_lo, u64 uuid_hi, u32 flags) ++{ ++ BUILD_BUG_ON((TMEM_POOL_PAGEORDER < 0) || ++ (TMEM_POOL_PAGEORDER >= TMEM_POOL_PAGESIZE_MASK)); ++ flags |= TMEM_POOL_PAGEORDER << TMEM_POOL_PAGESIZE_SHIFT; ++ return xen_tmem_new_pool(TMEM_NEW_POOL, uuid_lo, uuid_hi, flags); ++} ++ ++static inline int tmem_destroy_pool(u32 pool_id) ++{ ++ return xen_tmem_op(TMEM_DESTROY_POOL, pool_id, 0, 0, 0, 0, 0, 0); ++} ++#else ++struct tmem_op { ++ u32 cmd; ++ s32 pool_id; /* private > 0; shared < 0; 0 is invalid */ ++ union { ++ struct { /* for cmd == TMEM_NEW_POOL */ ++ u64 uuid[2]; ++ u32 flags; ++ } new; ++ struct { /* for cmd == TMEM_CONTROL */ ++ u32 subop; ++ u32 cli_id; ++ u32 arg1; ++ u32 arg2; ++ void *buf; ++ } ctrl; ++ struct { ++ u64 object; ++ u32 index; ++ u32 tmem_offset; ++ u32 pfn_offset; ++ u32 len; ++ unsigned long pfn; /* page frame */ ++ } gen; ++ } u; ++}; ++#endif +--- sle11sp1-2010-03-29.orig/mm/truncate.c 2010-03-29 09:00:36.000000000 +0200 ++++ sle11sp1-2010-03-29/mm/truncate.c 2010-03-01 14:16:22.000000000 +0100 +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + #include + #include /* grr. try_to_release_page, + do_invalidatepage */ +@@ -50,6 +51,7 @@ void do_invalidatepage(struct page *page + static inline void truncate_partial_page(struct page *page, unsigned partial) + { + zero_user_segment(page, partial, PAGE_CACHE_SIZE); ++ precache_flush(page->mapping, page->index); + if (page_has_private(page)) + do_invalidatepage(page, partial); + } +@@ -107,6 +109,10 @@ truncate_complete_page(struct address_sp + clear_page_mlock(page); + remove_from_page_cache(page); + ClearPageMappedToDisk(page); ++ /* this must be after the remove_from_page_cache which ++ * calls precache_put ++ */ ++ precache_flush(mapping, page->index); + page_cache_release(page); /* pagecache ref */ + return 0; + } +@@ -214,6 +220,7 @@ void truncate_inode_pages_range(struct a + pgoff_t next; + int i; + ++ precache_flush_inode(mapping); + if (mapping->nrpages == 0) + return; + +@@ -289,6 +296,7 @@ void truncate_inode_pages_range(struct a + pagevec_release(&pvec); + mem_cgroup_uncharge_end(); + } ++ precache_flush_inode(mapping); + } + EXPORT_SYMBOL(truncate_inode_pages_range); + +@@ -427,6 +435,7 @@ int invalidate_inode_pages2_range(struct + int did_range_unmap = 0; + int wrapped = 0; + ++ precache_flush_inode(mapping); + pagevec_init(&pvec, 0); + next = start; + while (next <= end && !wrapped && +@@ -485,6 +494,7 @@ int invalidate_inode_pages2_range(struct + mem_cgroup_uncharge_end(); + cond_resched(); + } ++ precache_flush_inode(mapping); + return ret; + } + EXPORT_SYMBOL_GPL(invalidate_inode_pages2_range); diff --git a/x86-Unify-fixup_irqs-for-32-bit-and-64-bit-kernels.patch b/x86-Unify-fixup_irqs-for-32-bit-and-64-bit-kernels.patch new file mode 100644 index 0000000..96a626d --- /dev/null +++ b/x86-Unify-fixup_irqs-for-32-bit-and-64-bit-kernels.patch @@ -0,0 +1,210 @@ +From: Suresh Siddha +Subject: x86: Unify fixup_irqs() for 32-bit and 64-bit kernels +References: bnc#558247 +Patch-upstream: Yes + +Commit 7a7732bc0f7c46f217dbec723f25366b6285cc42 upstream. + +There is no reason to have different fixup_irqs() for 32-bit +and 64-bit kernels. Unify by using the superior 64-bit version for +both the kernels. + +Signed-off-by: Suresh Siddha +Signed-off-by: Gary Hade +Signed-off-by: Ingo Molnar +Signed-off-by: Rafael J. Wysocki +--- + arch/x86/kernel/irq.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++ + arch/x86/kernel/irq_32.c | 45 ----------------------------------- + arch/x86/kernel/irq_64.c | 58 ---------------------------------------------- + 3 files changed, 59 insertions(+), 103 deletions(-) + +Index: linux-2.6.32-master/arch/x86/kernel/irq.c +=================================================================== +--- linux-2.6.32-master.orig/arch/x86/kernel/irq.c ++++ linux-2.6.32-master/arch/x86/kernel/irq.c +@@ -274,3 +274,62 @@ void smp_x86_platform_ipi(struct pt_regs + } + + EXPORT_SYMBOL_GPL(vector_used_by_percpu_irq); ++ ++#ifdef CONFIG_HOTPLUG_CPU ++/* A cpu has been removed from cpu_online_mask. Reset irq affinities. */ ++void fixup_irqs(void) ++{ ++ unsigned int irq; ++ static int warned; ++ struct irq_desc *desc; ++ ++ for_each_irq_desc(irq, desc) { ++ int break_affinity = 0; ++ int set_affinity = 1; ++ const struct cpumask *affinity; ++ ++ if (!desc) ++ continue; ++ if (irq == 2) ++ continue; ++ ++ /* interrupt's are disabled at this point */ ++ spin_lock(&desc->lock); ++ ++ affinity = desc->affinity; ++ if (!irq_has_action(irq) || ++ cpumask_equal(affinity, cpu_online_mask)) { ++ spin_unlock(&desc->lock); ++ continue; ++ } ++ ++ if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) { ++ break_affinity = 1; ++ affinity = cpu_all_mask; ++ } ++ ++ if (desc->chip->mask) ++ desc->chip->mask(irq); ++ ++ if (desc->chip->set_affinity) ++ desc->chip->set_affinity(irq, affinity); ++ else if (!(warned++)) ++ set_affinity = 0; ++ ++ if (desc->chip->unmask) ++ desc->chip->unmask(irq); ++ ++ spin_unlock(&desc->lock); ++ ++ if (break_affinity && set_affinity) ++ printk("Broke affinity for irq %i\n", irq); ++ else if (!set_affinity) ++ printk("Cannot set affinity for irq %i\n", irq); ++ } ++ ++ /* That doesn't seem sufficient. Give it 1ms. */ ++ local_irq_enable(); ++ mdelay(1); ++ local_irq_disable(); ++} ++#endif +Index: linux-2.6.32-master/arch/x86/kernel/irq_32.c +=================================================================== +--- linux-2.6.32-master.orig/arch/x86/kernel/irq_32.c ++++ linux-2.6.32-master/arch/x86/kernel/irq_32.c +@@ -211,48 +211,3 @@ bool handle_irq(unsigned irq, struct pt_ + + return true; + } +- +-#ifdef CONFIG_HOTPLUG_CPU +- +-/* A cpu has been removed from cpu_online_mask. Reset irq affinities. */ +-void fixup_irqs(void) +-{ +- unsigned int irq; +- struct irq_desc *desc; +- +- for_each_irq_desc(irq, desc) { +- const struct cpumask *affinity; +- +- if (!desc) +- continue; +- if (irq == 2) +- continue; +- +- affinity = desc->affinity; +- if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) { +- printk("Breaking affinity for irq %i\n", irq); +- affinity = cpu_all_mask; +- } +- if (desc->chip->set_affinity) +- desc->chip->set_affinity(irq, affinity); +- else if (desc->action) +- printk_once("Cannot set affinity for irq %i\n", irq); +- } +- +-#if 0 +- barrier(); +- /* Ingo Molnar says: "after the IO-APIC masks have been redirected +- [note the nop - the interrupt-enable boundary on x86 is two +- instructions from sti] - to flush out pending hardirqs and +- IPIs. After this point nothing is supposed to reach this CPU." */ +- __asm__ __volatile__("sti; nop; cli"); +- barrier(); +-#else +- /* That doesn't seem sufficient. Give it 1ms. */ +- local_irq_enable(); +- mdelay(1); +- local_irq_disable(); +-#endif +-} +-#endif +- +Index: linux-2.6.32-master/arch/x86/kernel/irq_64.c +=================================================================== +--- linux-2.6.32-master.orig/arch/x86/kernel/irq_64.c ++++ linux-2.6.32-master/arch/x86/kernel/irq_64.c +@@ -62,64 +62,6 @@ bool handle_irq(unsigned irq, struct pt_ + return true; + } + +-#ifdef CONFIG_HOTPLUG_CPU +-/* A cpu has been removed from cpu_online_mask. Reset irq affinities. */ +-void fixup_irqs(void) +-{ +- unsigned int irq; +- static int warned; +- struct irq_desc *desc; +- +- for_each_irq_desc(irq, desc) { +- int break_affinity = 0; +- int set_affinity = 1; +- const struct cpumask *affinity; +- +- if (!desc) +- continue; +- if (irq == 2) +- continue; +- +- /* interrupt's are disabled at this point */ +- spin_lock(&desc->lock); +- +- affinity = desc->affinity; +- if (!irq_has_action(irq) || +- cpumask_equal(affinity, cpu_online_mask)) { +- spin_unlock(&desc->lock); +- continue; +- } +- +- if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) { +- break_affinity = 1; +- affinity = cpu_all_mask; +- } +- +- if (desc->chip->mask) +- desc->chip->mask(irq); +- +- if (desc->chip->set_affinity) +- desc->chip->set_affinity(irq, affinity); +- else if (!(warned++)) +- set_affinity = 0; +- +- if (desc->chip->unmask) +- desc->chip->unmask(irq); +- +- spin_unlock(&desc->lock); +- +- if (break_affinity && set_affinity) +- printk("Broke affinity for irq %i\n", irq); +- else if (!set_affinity) +- printk("Cannot set affinity for irq %i\n", irq); +- } +- +- /* That doesn't seem sufficient. Give it 1ms. */ +- local_irq_enable(); +- mdelay(1); +- local_irq_disable(); +-} +-#endif + + extern void call_softirq(void); + diff --git a/x86-cpu-mv-display_cacheinfo-cpu_detect_cache_sizes.patch b/x86-cpu-mv-display_cacheinfo-cpu_detect_cache_sizes.patch new file mode 100644 index 0000000..ceb9074 --- /dev/null +++ b/x86-cpu-mv-display_cacheinfo-cpu_detect_cache_sizes.patch @@ -0,0 +1,96 @@ +From: Borislav Petkov +Subject: x86, cpu: mv display_cacheinfo -> cpu_detect_cache_sizes +Patch-mainline: 2.6.33-rc1 +References: bnc#564618, FATE#306952 +Git-commit: 27c13ecec4d8856687b50b959e1146845b478f95 + +display_cacheinfo() doesn't display anything anymore and it is used to +detect CPU cache sizes. Rename it accordingly. + +Signed-off-by: Borislav Petkov +LKML-Reference: <20091121130145.GA31357@liondog.tnic> +Signed-off-by: H. Peter Anvin +Signed-off-by: Rafael J. Wysocki +--- + arch/x86/kernel/cpu/amd.c | 2 +- + arch/x86/kernel/cpu/centaur.c | 2 +- + arch/x86/kernel/cpu/common.c | 4 ++-- + arch/x86/kernel/cpu/cpu.h | 2 +- + arch/x86/kernel/cpu/cyrix.c | 2 +- + arch/x86/kernel/cpu/transmeta.c | 2 +- + 6 files changed, 7 insertions(+), 7 deletions(-) + +--- a/arch/x86/kernel/cpu/amd.c ++++ b/arch/x86/kernel/cpu/amd.c +@@ -535,7 +535,7 @@ static void __cpuinit init_amd(struct cp + } + } + +- display_cacheinfo(c); ++ cpu_detect_cache_sizes(c); + + /* Multi core CPU? */ + if (c->extended_cpuid_level >= 0x80000008) { +--- a/arch/x86/kernel/cpu/centaur.c ++++ b/arch/x86/kernel/cpu/centaur.c +@@ -294,7 +294,7 @@ static void __cpuinit init_c3(struct cpu + set_cpu_cap(c, X86_FEATURE_REP_GOOD); + } + +- display_cacheinfo(c); ++ cpu_detect_cache_sizes(c); + } + + enum { +--- a/arch/x86/kernel/cpu/common.c ++++ b/arch/x86/kernel/cpu/common.c +@@ -61,7 +61,7 @@ void __init setup_cpu_local_masks(void) + static void __cpuinit default_init(struct cpuinfo_x86 *c) + { + #ifdef CONFIG_X86_64 +- display_cacheinfo(c); ++ cpu_detect_cache_sizes(c); + #else + /* Not much we can do here... */ + /* Check if at least it has cpuid */ +@@ -383,7 +383,7 @@ static void __cpuinit get_model_name(str + } + } + +-void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c) ++void __cpuinit cpu_detect_cache_sizes(struct cpuinfo_x86 *c) + { + unsigned int n, dummy, ebx, ecx, edx, l2size; + +--- a/arch/x86/kernel/cpu/cpu.h ++++ b/arch/x86/kernel/cpu/cpu.h +@@ -32,6 +32,6 @@ struct cpu_dev { + extern const struct cpu_dev *const __x86_cpu_dev_start[], + *const __x86_cpu_dev_end[]; + +-extern void display_cacheinfo(struct cpuinfo_x86 *c); ++extern void cpu_detect_cache_sizes(struct cpuinfo_x86 *c); + + #endif +--- a/arch/x86/kernel/cpu/cyrix.c ++++ b/arch/x86/kernel/cpu/cyrix.c +@@ -373,7 +373,7 @@ static void __cpuinit init_nsc(struct cp + /* Handle the GX (Formally known as the GX2) */ + + if (c->x86 == 5 && c->x86_model == 5) +- display_cacheinfo(c); ++ cpu_detect_cache_sizes(c); + else + init_cyrix(c); + } +--- a/arch/x86/kernel/cpu/transmeta.c ++++ b/arch/x86/kernel/cpu/transmeta.c +@@ -26,7 +26,7 @@ static void __cpuinit init_transmeta(str + + early_init_transmeta(c); + +- display_cacheinfo(c); ++ cpu_detect_cache_sizes(c); + + /* Print CMS and CPU revision */ + max = cpuid_eax(0x80860000); diff --git a/x86_64_defconfig-server b/x86_64_defconfig-server new file mode 100644 index 0000000..2e16cd5 --- /dev/null +++ b/x86_64_defconfig-server @@ -0,0 +1,4762 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_64BIT=y +# CONFIG_X86_32 is not set +CONFIG_X86_64=y +CONFIG_X86=y +CONFIG_OUTPUT_FORMAT="elf64-x86-64" +CONFIG_ARCH_DEFCONFIG="arch/x86/configs/x86_64_defconfig" +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CMOS_UPDATE=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_MMU=y +CONFIG_ZONE_DMA=y +CONFIG_GENERIC_ISA_DMA=y +CONFIG_GENERIC_IOMAP=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_GPIO=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set +CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_ARCH_HAS_CPU_RELAX=y +CONFIG_ARCH_HAS_DEFAULT_IDLE=y +CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y +CONFIG_HAVE_SETUP_PER_CPU_AREA=y +CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y +CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y +CONFIG_HAVE_CPUMASK_OF_CPU_MAP=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ZONE_DMA32=y +CONFIG_ARCH_POPULATES_NODE_MAP=y +CONFIG_AUDIT_ARCH=y +CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y +CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_PENDING_IRQ=y +CONFIG_USE_GENERIC_SMP_HELPERS=y +CONFIG_X86_64_SMP=y +CONFIG_X86_NO_TSS=y +CONFIG_X86_NO_IDT=y +# CONFIG_KTIME_SCALAR is not set +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_CONSTRUCTORS=y + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="-xen" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_HAVE_KERNEL_GZIP=y +CONFIG_KERNEL_GZIP=y +# CONFIG_KERNEL_BZIP2 is not set +# CONFIG_KERNEL_LZMA is not set +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_POSIX_MQUEUE=y +CONFIG_POSIX_MQUEUE_SYSCTL=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_TASK_XACCT=y +CONFIG_TASK_IO_ACCOUNTING=y +CONFIG_AUDIT=y +CONFIG_AUDITSYSCALL=y +CONFIG_AUDIT_TREE=y + +# +# RCU Subsystem +# +CONFIG_TREE_RCU=y +# CONFIG_TREE_PREEMPT_RCU is not set +# CONFIG_RCU_TRACE is not set +CONFIG_RCU_FANOUT=64 +# CONFIG_RCU_FANOUT_EXACT is not set +# CONFIG_TREE_RCU_TRACE is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=18 +CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y +CONFIG_GROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +CONFIG_RT_GROUP_SCHED=y +# CONFIG_USER_SCHED is not set +CONFIG_CGROUP_SCHED=y +CONFIG_CGROUPS=y +# CONFIG_CGROUP_DEBUG is not set +CONFIG_CGROUP_NS=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_DEVICE=y +CONFIG_CPUSETS=y +CONFIG_PROC_PID_CPUSET=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_RESOURCE_COUNTERS=y +CONFIG_CGROUP_MEM_RES_CTLR=y +# CONFIG_CGROUP_MEM_RES_CTLR_SWAP is not set +CONFIG_MM_OWNER=y +# CONFIG_SYSFS_DEPRECATED_V2 is not set +CONFIG_RELAY=y +CONFIG_NAMESPACES=y +CONFIG_UTS_NS=y +CONFIG_IPC_NS=y +CONFIG_USER_NS=y +CONFIG_PID_NS=y +CONFIG_NET_NS=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +CONFIG_RD_BZIP2=y +CONFIG_RD_LZMA=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +# CONFIG_EMBEDDED is not set +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_ALL=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_PCSPKR_PLATFORM=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y + +# +# Kernel Performance Events And Counters +# +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_PCI_QUIRKS=y +CONFIG_COMPAT_BRK=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +CONFIG_PROFILING=y +CONFIG_OPROFILE=m +# CONFIG_OPROFILE_EVENT_MULTIPLEX is not set +CONFIG_HAVE_OPROFILE=y +CONFIG_KPROBES=y +CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y +CONFIG_KRETPROBES=y +CONFIG_HAVE_IOREMAP_PROT=y +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +CONFIG_HAVE_DMA_ATTRS=y +CONFIG_HAVE_DMA_API_DEBUG=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +CONFIG_SLOW_WORK=y +CONFIG_SLOW_WORK_DEBUG=y +# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +CONFIG_MODULE_FORCE_LOAD=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_STOP_MACHINE=y +CONFIG_BLOCK=y +CONFIG_BLK_DEV_BSG=y +CONFIG_BLK_DEV_INTEGRITY=y +CONFIG_BLOCK_COMPAT=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +CONFIG_FREEZER=y + +# +# Processor type and features +# +CONFIG_SMP=y +CONFIG_SPARSE_IRQ=y +CONFIG_X86_MPPARSE=y +CONFIG_X86_64_XEN=y +CONFIG_X86_SUPPORTS_MEMORY_FAILURE=y +CONFIG_SCHED_OMIT_FRAME_POINTER=y +# CONFIG_M386 is not set +# CONFIG_M486 is not set +# CONFIG_M586 is not set +# CONFIG_M586TSC is not set +# CONFIG_M586MMX is not set +# CONFIG_M686 is not set +# CONFIG_MPENTIUMII is not set +# CONFIG_MPENTIUMIII is not set +# CONFIG_MPENTIUMM is not set +# CONFIG_MPENTIUM4 is not set +# CONFIG_MK6 is not set +# CONFIG_MK7 is not set +# CONFIG_MK8 is not set +# CONFIG_MCRUSOE is not set +# CONFIG_MEFFICEON is not set +# CONFIG_MWINCHIPC6 is not set +# CONFIG_MWINCHIP3D is not set +# CONFIG_MGEODEGX1 is not set +# CONFIG_MGEODE_LX is not set +# CONFIG_MCYRIXIII is not set +# CONFIG_MVIAC3_2 is not set +# CONFIG_MVIAC7 is not set +# CONFIG_MPSC is not set +# CONFIG_MCORE2 is not set +# CONFIG_MATOM is not set +CONFIG_GENERIC_CPU=y +CONFIG_X86_CPU=y +CONFIG_X86_L1_CACHE_BYTES=64 +CONFIG_X86_INTERNODE_CACHE_BYTES=64 +CONFIG_X86_CMPXCHG=y +CONFIG_X86_L1_CACHE_SHIFT=6 +CONFIG_X86_WP_WORKS_OK=y +CONFIG_X86_CMPXCHG64=y +CONFIG_X86_CMOV=y +CONFIG_X86_MINIMUM_CPU_FAMILY=64 +CONFIG_X86_DEBUGCTLMSR=y +CONFIG_CPU_SUP_INTEL=y +CONFIG_CPU_SUP_AMD=y +CONFIG_CPU_SUP_CENTAUR=y +CONFIG_DMI=y +CONFIG_SWIOTLB=y +CONFIG_IOMMU_HELPER=y +# CONFIG_IOMMU_API is not set +# CONFIG_MAXSMP is not set +CONFIG_NR_CPUS=512 +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_X86_LOCAL_APIC=y +CONFIG_X86_IO_APIC=y +CONFIG_X86_MCE=y +CONFIG_X86_MCE_INJECT=m +CONFIG_X86_XEN_MCE=y +CONFIG_I8K=m +CONFIG_MICROCODE=m +CONFIG_MICROCODE_OLD_INTERFACE=y +CONFIG_X86_MSR=m +CONFIG_X86_CPUID=m +CONFIG_ARCH_PHYS_ADDR_T_64BIT=y +CONFIG_ARCH_PROC_KCORE_TEXT=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_PHYS_ADDR_T_64BIT=y +CONFIG_ZONE_DMA_FLAG=1 +CONFIG_BOUNCE=y +CONFIG_VIRT_TO_BUS=y +CONFIG_HAVE_MLOCK=y +CONFIG_HAVE_MLOCKED_PAGE_BIT=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=65536 +CONFIG_ARCH_SUPPORTS_MEMORY_FAILURE=y +CONFIG_MEMORY_FAILURE=y +CONFIG_HWPOISON_INJECT=m +CONFIG_TMEM=y +CONFIG_PRECACHE=y +CONFIG_PRESWAP=y +CONFIG_MTRR=y +CONFIG_X86_PAT=y +CONFIG_ARCH_USES_PG_UNCACHED=y +CONFIG_SECCOMP=y +# CONFIG_CC_STACKPROTECTOR is not set +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_300 is not set +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +# CONFIG_SCHED_HRTICK is not set +CONFIG_KEXEC=y +CONFIG_PHYSICAL_START=0x2000 +CONFIG_PHYSICAL_ALIGN=0x2000 +CONFIG_HOTPLUG_CPU=y +CONFIG_COMPAT_VDSO=y +# CONFIG_CMDLINE_BOOL is not set + +# +# Power management and ACPI options +# +CONFIG_PM=y +CONFIG_PM_DEBUG=y +# CONFIG_PM_VERBOSE is not set +CONFIG_CAN_PM_TRACE=y +CONFIG_PM_TRACE=y +CONFIG_PM_TRACE_RTC=y +CONFIG_PM_SLEEP_SMP=y +CONFIG_PM_SLEEP=y +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +CONFIG_PM_RUNTIME=y +CONFIG_ACPI=y +CONFIG_ACPI_SLEEP=y +CONFIG_ACPI_PROCFS=y +CONFIG_ACPI_PROCFS_POWER=y +CONFIG_ACPI_POWER_METER=m +CONFIG_ACPI_SYSFS_POWER=y +CONFIG_ACPI_PROC_EVENT=y +CONFIG_ACPI_AC=m +CONFIG_ACPI_BATTERY=m +CONFIG_ACPI_BUTTON=m +CONFIG_ACPI_VIDEO=m +CONFIG_ACPI_FAN=m +CONFIG_ACPI_DOCK=y +CONFIG_ACPI_PROCESSOR=m +CONFIG_ACPI_HOTPLUG_CPU=y +CONFIG_ACPI_PROCESSOR_AGGREGATOR=m +CONFIG_ACPI_THERMAL=m +CONFIG_ACPI_CUSTOM_DSDT_FILE="" +# CONFIG_ACPI_CUSTOM_DSDT is not set +CONFIG_ACPI_BLACKLIST_YEAR=0 +CONFIG_ACPI_DEBUG=y +# CONFIG_ACPI_DEBUG_FUNC_TRACE is not set +CONFIG_ACPI_PCI_SLOT=m +CONFIG_ACPI_CONTAINER=m +CONFIG_ACPI_SBS=m +CONFIG_ACPI_PV_SLEEP=y +CONFIG_PROCESSOR_EXTERNAL_CONTROL=y +CONFIG_SFI=y + +# +# CPU Frequency scaling +# + +# +# Memory power savings +# +CONFIG_I7300_IDLE_IOAT_CHANNEL=y +CONFIG_I7300_IDLE=m + +# +# Bus options (PCI etc.) +# +CONFIG_PCI=y +CONFIG_PCI_DIRECT=y +CONFIG_PCI_MMCONFIG=y +CONFIG_PCI_DOMAINS=y +CONFIG_XEN_PCIDEV_FRONTEND=y +# CONFIG_XEN_PCIDEV_FE_DEBUG is not set +CONFIG_PCIEPORTBUS=y +CONFIG_HOTPLUG_PCI_PCIE=m +CONFIG_PCIEAER=y +# CONFIG_PCIE_ECRC is not set +CONFIG_PCIEAER_INJECT=m +CONFIG_PCIEASPM=y +# CONFIG_PCIEASPM_DEBUG is not set +CONFIG_ARCH_SUPPORTS_MSI=y +CONFIG_PCI_MSI=y +CONFIG_PCI_LEGACY=y +# CONFIG_PCI_DEBUG is not set +CONFIG_PCI_GUESTDEV=y +CONFIG_PCI_IOMULTI=y +CONFIG_PCI_RESERVE=y +CONFIG_PCI_STUB=y +CONFIG_PCI_IOV=y +CONFIG_ISA_DMA_API=y +CONFIG_K8_NB=y +CONFIG_PCCARD=m +# CONFIG_PCMCIA_DEBUG is not set +CONFIG_PCMCIA=m +CONFIG_PCMCIA_LOAD_CIS=y +CONFIG_PCMCIA_IOCTL=y +CONFIG_CARDBUS=y + +# +# PC-card bridges +# +CONFIG_YENTA=m +CONFIG_YENTA_O2=y +CONFIG_YENTA_RICOH=y +CONFIG_YENTA_TI=y +CONFIG_YENTA_ENE_TUNE=y +CONFIG_YENTA_TOSHIBA=y +CONFIG_PD6729=m +CONFIG_I82092=m +CONFIG_PCCARD_NONSTATIC=m +CONFIG_HOTPLUG_PCI=m +CONFIG_HOTPLUG_PCI_FAKE=m +CONFIG_HOTPLUG_PCI_ACPI=m +CONFIG_HOTPLUG_PCI_ACPI_IBM=m +CONFIG_HOTPLUG_PCI_CPCI=y +CONFIG_HOTPLUG_PCI_CPCI_ZT5550=m +CONFIG_HOTPLUG_PCI_CPCI_GENERIC=m +CONFIG_HOTPLUG_PCI_SHPC=m + +# +# Executable file formats / Emulations +# +CONFIG_BINFMT_ELF=y +CONFIG_COMPAT_BINFMT_ELF=y +CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y +# CONFIG_HAVE_AOUT is not set +CONFIG_BINFMT_MISC=m +CONFIG_IA32_EMULATION=y +CONFIG_IA32_AOUT=m +CONFIG_COMPAT=y +CONFIG_COMPAT_FOR_U64_ALIGNMENT=y +CONFIG_SYSVIPC_COMPAT=y +CONFIG_NET=y +CONFIG_COMPAT_NETLINK_MESSAGES=y + +# +# Networking options +# +CONFIG_PACKET=m +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +CONFIG_XFRM_USER=m +CONFIG_XFRM_SUB_POLICY=y +CONFIG_XFRM_MIGRATE=y +# CONFIG_XFRM_STATISTICS is not set +CONFIG_XFRM_IPCOMP=m +CONFIG_NET_KEY=m +CONFIG_NET_KEY_MIGRATE=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_ASK_IP_FIB_HASH=y +# CONFIG_IP_FIB_TRIE is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=y +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +CONFIG_INET_XFRM_TUNNEL=m +CONFIG_INET_TUNNEL=m +CONFIG_INET_XFRM_MODE_TRANSPORT=m +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_XFRM_MODE_BEET=m +CONFIG_INET_LRO=y +CONFIG_INET_DIAG=m +CONFIG_INET_TCP_DIAG=m +CONFIG_TCP_CONG_ADVANCED=y +CONFIG_TCP_CONG_BIC=m +CONFIG_TCP_CONG_CUBIC=y +CONFIG_TCP_CONG_WESTWOOD=m +CONFIG_TCP_CONG_HTCP=m +CONFIG_TCP_CONG_HSTCP=m +CONFIG_TCP_CONG_HYBLA=m +CONFIG_TCP_CONG_VEGAS=m +CONFIG_TCP_CONG_SCALABLE=m +CONFIG_TCP_CONG_LP=m +CONFIG_TCP_CONG_VENO=m +CONFIG_TCP_CONG_YEAH=m +CONFIG_TCP_CONG_ILLINOIS=m +# CONFIG_DEFAULT_BIC is not set +CONFIG_DEFAULT_CUBIC=y +# CONFIG_DEFAULT_HTCP is not set +# CONFIG_DEFAULT_VEGAS is not set +# CONFIG_DEFAULT_WESTWOOD is not set +# CONFIG_DEFAULT_RENO is not set +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +CONFIG_IPV6=m +CONFIG_IPV6_PRIVACY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +# CONFIG_IPV6_OPTIMISTIC_DAD is not set +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_IPV6_MIP6=m +CONFIG_INET6_XFRM_TUNNEL=m +CONFIG_INET6_TUNNEL=m +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_INET6_XFRM_MODE_BEET=m +CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m +CONFIG_IPV6_SIT=m +CONFIG_IPV6_NDISC_NODETYPE=y +CONFIG_IPV6_TUNNEL=m +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +# CONFIG_IPV6_MROUTE is not set +CONFIG_NETLABEL=y +CONFIG_NETWORK_SECMARK=y +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_NETFILTER_ADVANCED=y +CONFIG_BRIDGE_NETFILTER=y + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_NETLINK=m +CONFIG_NETFILTER_NETLINK_QUEUE=m +CONFIG_NETFILTER_NETLINK_LOG=m +CONFIG_NF_CONNTRACK=m +CONFIG_NF_CT_ACCT=y +CONFIG_NF_CONNTRACK_MARK=y +CONFIG_NF_CONNTRACK_SECMARK=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CT_PROTO_DCCP=m +CONFIG_NF_CT_PROTO_GRE=m +CONFIG_NF_CT_PROTO_SCTP=m +CONFIG_NF_CT_PROTO_UDPLITE=m +CONFIG_NF_CONNTRACK_AMANDA=m +CONFIG_NF_CONNTRACK_FTP=m +CONFIG_NF_CONNTRACK_H323=m +CONFIG_NF_CONNTRACK_IRC=m +CONFIG_NF_CONNTRACK_NETBIOS_NS=m +CONFIG_NF_CONNTRACK_PPTP=m +CONFIG_NF_CONNTRACK_SANE=m +CONFIG_NF_CONNTRACK_SIP=m +CONFIG_NF_CONNTRACK_TFTP=m +CONFIG_NF_CT_NETLINK=m +CONFIG_NETFILTER_TPROXY=m +CONFIG_NETFILTER_XTABLES=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m +CONFIG_NETFILTER_XT_TARGET_DSCP=m +CONFIG_NETFILTER_XT_TARGET_HL=m +CONFIG_NETFILTER_XT_TARGET_LED=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFLOG=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_TARGET_RATEEST=m +CONFIG_NETFILTER_XT_TARGET_TPROXY=m +CONFIG_NETFILTER_XT_TARGET_TRACE=m +CONFIG_NETFILTER_XT_TARGET_SECMARK=m +CONFIG_NETFILTER_XT_TARGET_TCPMSS=m +CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m +CONFIG_NETFILTER_XT_MATCH_CLUSTER=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_DSCP=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_HL=m +CONFIG_NETFILTER_XT_MATCH_IPRANGE=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_OWNER=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_RATEEST=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_RECENT=m +# CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT is not set +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_SOCKET=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m +CONFIG_NETFILTER_XT_MATCH_TIME=m +CONFIG_NETFILTER_XT_MATCH_U32=m +CONFIG_NETFILTER_XT_MATCH_OSF=m +CONFIG_IP_VS=m +CONFIG_IP_VS_IPV6=y +# CONFIG_IP_VS_DEBUG is not set +CONFIG_IP_VS_TAB_BITS=12 + +# +# IPVS transport protocol load balancing support +# +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_AH_ESP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y + +# +# IPVS scheduler +# +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m + +# +# IPVS application helper +# +CONFIG_IP_VS_FTP=m + +# +# IP: Netfilter Configuration +# +CONFIG_NF_DEFRAG_IPV4=m +CONFIG_NF_CONNTRACK_IPV4=m +# CONFIG_NF_CONNTRACK_PROC_COMPAT is not set +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_ADDRTYPE=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_NF_NAT=m +CONFIG_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_NF_NAT_SNMP_BASIC=m +CONFIG_NF_NAT_PROTO_DCCP=m +CONFIG_NF_NAT_PROTO_GRE=m +CONFIG_NF_NAT_PROTO_UDPLITE=m +CONFIG_NF_NAT_PROTO_SCTP=m +CONFIG_NF_NAT_FTP=m +CONFIG_NF_NAT_IRC=m +CONFIG_NF_NAT_TFTP=m +CONFIG_NF_NAT_AMANDA=m +CONFIG_NF_NAT_PPTP=m +CONFIG_NF_NAT_H323=m +CONFIG_NF_NAT_SIP=m +CONFIG_IP_NF_MANGLE=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_TARGET_TTL=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_SECURITY=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m + +# +# IPv6: Netfilter Configuration +# +CONFIG_NF_CONNTRACK_IPV6=m +CONFIG_IP6_NF_QUEUE=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_MH=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_TARGET_LOG=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_RAW=m +CONFIG_IP6_NF_SECURITY=m + +# +# DECnet: Netfilter Configuration +# +# CONFIG_DECNET_NF_GRABULATOR is not set +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_IP6=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_ULOG=m +CONFIG_BRIDGE_EBT_NFLOG=m +CONFIG_IP_DCCP=m +CONFIG_INET_DCCP_DIAG=m + +# +# DCCP CCIDs Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP_CCID2_DEBUG is not set +CONFIG_IP_DCCP_CCID3=y +# CONFIG_IP_DCCP_CCID3_DEBUG is not set +CONFIG_IP_DCCP_CCID3_RTO=100 +CONFIG_IP_DCCP_TFRC_LIB=y + +# +# DCCP Kernel Hacking +# +# CONFIG_IP_DCCP_DEBUG is not set +# CONFIG_NET_DCCPPROBE is not set +CONFIG_IP_SCTP=m +# CONFIG_SCTP_DBG_MSG is not set +# CONFIG_SCTP_DBG_OBJCNT is not set +# CONFIG_SCTP_HMAC_NONE is not set +# CONFIG_SCTP_HMAC_SHA1 is not set +CONFIG_SCTP_HMAC_MD5=y +CONFIG_RDS=m +CONFIG_RDS_RDMA=m +CONFIG_RDS_TCP=m +# CONFIG_RDS_DEBUG is not set +# CONFIG_TIPC is not set +CONFIG_ATM=m +CONFIG_ATM_CLIP=m +# CONFIG_ATM_CLIP_NO_ICMP is not set +CONFIG_ATM_LANE=m +CONFIG_ATM_MPOA=m +CONFIG_ATM_BR2684=m +# CONFIG_ATM_BR2684_IPFILTER is not set +CONFIG_STP=m +CONFIG_GARP=m +CONFIG_BRIDGE=m +CONFIG_NET_DSA=y +CONFIG_NET_DSA_TAG_DSA=y +CONFIG_NET_DSA_TAG_EDSA=y +CONFIG_NET_DSA_TAG_TRAILER=y +CONFIG_NET_DSA_MV88E6XXX=y +CONFIG_NET_DSA_MV88E6060=y +CONFIG_NET_DSA_MV88E6XXX_NEED_PPU=y +CONFIG_NET_DSA_MV88E6131=y +CONFIG_NET_DSA_MV88E6123_61_65=y +CONFIG_VLAN_8021Q=m +CONFIG_VLAN_8021Q_GVRP=y +CONFIG_DECNET=m +# CONFIG_DECNET_ROUTER is not set +CONFIG_LLC=m +CONFIG_LLC2=m +CONFIG_IPX=m +CONFIG_IPX_INTERN=y +CONFIG_ATALK=m +CONFIG_DEV_APPLETALK=m +CONFIG_IPDDP=m +CONFIG_IPDDP_ENCAP=y +CONFIG_IPDDP_DECAP=y +CONFIG_X25=m +CONFIG_LAPB=m +# CONFIG_ECONET is not set +CONFIG_WAN_ROUTER=m +CONFIG_PHONET=m +CONFIG_IEEE802154=m +CONFIG_NET_SCHED=y + +# +# Queueing/Scheduling +# +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_ATM=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_MULTIQ=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_DRR=m +CONFIG_NET_SCH_INGRESS=m + +# +# Classification +# +CONFIG_NET_CLS=y +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_ROUTE=y +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_CLS_FLOW=m +CONFIG_NET_CLS_CGROUP=y +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_STACK=32 +CONFIG_NET_EMATCH_CMP=m +CONFIG_NET_EMATCH_NBYTE=m +CONFIG_NET_EMATCH_U32=m +CONFIG_NET_EMATCH_META=m +CONFIG_NET_EMATCH_TEXT=m +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=m +CONFIG_NET_ACT_GACT=m +CONFIG_GACT_PROB=y +CONFIG_NET_ACT_MIRRED=m +CONFIG_NET_ACT_IPT=m +CONFIG_NET_ACT_NAT=m +CONFIG_NET_ACT_PEDIT=m +CONFIG_NET_ACT_SIMP=m +CONFIG_NET_ACT_SKBEDIT=m +CONFIG_NET_CLS_IND=y +CONFIG_NET_SCH_FIFO=y +CONFIG_DCB=y + +# +# Network testing +# +CONFIG_NET_PKTGEN=m +CONFIG_NET_TCPPROBE=m +CONFIG_HAMRADIO=y + +# +# Packet Radio protocols +# +CONFIG_AX25=m +CONFIG_AX25_DAMA_SLAVE=y +CONFIG_NETROM=m +CONFIG_ROSE=m + +# +# AX.25 network device drivers +# +CONFIG_MKISS=m +CONFIG_6PACK=m +CONFIG_BPQETHER=m +CONFIG_BAYCOM_SER_FDX=m +CONFIG_BAYCOM_SER_HDX=m +CONFIG_BAYCOM_PAR=m +CONFIG_YAM=m +CONFIG_CAN=m +CONFIG_CAN_RAW=m +CONFIG_CAN_BCM=m + +# +# CAN Device Drivers +# +CONFIG_CAN_VCAN=m +CONFIG_CAN_DEV=m +CONFIG_CAN_CALC_BITTIMING=y +CONFIG_CAN_SJA1000=m +CONFIG_CAN_SJA1000_PLATFORM=m +CONFIG_CAN_EMS_PCI=m +CONFIG_CAN_KVASER_PCI=m + +# +# CAN USB interfaces +# +CONFIG_CAN_EMS_USB=m +# CONFIG_CAN_DEBUG_DEVICES is not set +CONFIG_IRDA=m + +# +# IrDA protocols +# +CONFIG_IRLAN=m +CONFIG_IRNET=m +CONFIG_IRCOMM=m +CONFIG_IRDA_ULTRA=y + +# +# IrDA options +# +CONFIG_IRDA_CACHE_LAST_LSAP=y +# CONFIG_IRDA_FAST_RR is not set +# CONFIG_IRDA_DEBUG is not set + +# +# Infrared-port device drivers +# + +# +# SIR device drivers +# +CONFIG_IRTTY_SIR=m + +# +# Dongle support +# +CONFIG_DONGLE=y +CONFIG_ESI_DONGLE=m +CONFIG_ACTISYS_DONGLE=m +CONFIG_TEKRAM_DONGLE=m +CONFIG_TOIM3232_DONGLE=m +CONFIG_LITELINK_DONGLE=m +CONFIG_MA600_DONGLE=m +CONFIG_GIRBIL_DONGLE=m +CONFIG_MCP2120_DONGLE=m +CONFIG_OLD_BELKIN_DONGLE=m +CONFIG_ACT200L_DONGLE=m +CONFIG_KINGSUN_DONGLE=m +CONFIG_KSDAZZLE_DONGLE=m +CONFIG_KS959_DONGLE=m + +# +# FIR device drivers +# +CONFIG_USB_IRDA=m +CONFIG_SIGMATEL_FIR=m +CONFIG_NSC_FIR=m +CONFIG_WINBOND_FIR=m +CONFIG_SMC_IRCC_FIR=m +CONFIG_ALI_FIR=m +CONFIG_VLSI_FIR=m +CONFIG_VIA_FIR=m +CONFIG_MCS_FIR=m +CONFIG_BT=m +CONFIG_BT_L2CAP=m +CONFIG_BT_SCO=m +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_CMTP=m +CONFIG_BT_HIDP=m + +# +# Bluetooth device drivers +# +CONFIG_BT_HCIBTUSB=m +CONFIG_BT_HCIBTSDIO=m +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_H4=y +CONFIG_BT_HCIUART_BCSP=y +CONFIG_BT_HCIUART_LL=y +CONFIG_BT_HCIBCM203X=m +CONFIG_BT_HCIBPA10X=m +CONFIG_BT_HCIBFUSB=m +CONFIG_BT_HCIDTL1=m +CONFIG_BT_HCIBT3C=m +CONFIG_BT_HCIBLUECARD=m +CONFIG_BT_HCIBTUART=m +CONFIG_BT_HCIVHCI=m +CONFIG_BT_MRVL=m +CONFIG_BT_MRVL_SDIO=m +CONFIG_AF_RXRPC=m +# CONFIG_AF_RXRPC_DEBUG is not set +CONFIG_RXKAD=m +CONFIG_FIB_RULES=y +CONFIG_WIRELESS=y +CONFIG_CFG80211=m +# CONFIG_NL80211_TESTMODE is not set +# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set +# CONFIG_CFG80211_REG_DEBUG is not set +CONFIG_CFG80211_DEFAULT_PS=y +CONFIG_CFG80211_DEFAULT_PS_VALUE=1 +# CONFIG_CFG80211_DEBUGFS is not set +# CONFIG_WIRELESS_OLD_REGULATORY is not set +CONFIG_WIRELESS_EXT=y +CONFIG_WIRELESS_EXT_SYSFS=y +CONFIG_LIB80211=m +CONFIG_LIB80211_CRYPT_WEP=m +CONFIG_LIB80211_CRYPT_CCMP=m +CONFIG_LIB80211_CRYPT_TKIP=m +# CONFIG_LIB80211_DEBUG is not set +CONFIG_MAC80211=m +CONFIG_MAC80211_RC_MINSTREL=y +# CONFIG_MAC80211_RC_DEFAULT_PID is not set +CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y +CONFIG_MAC80211_RC_DEFAULT="minstrel" +CONFIG_MAC80211_MESH=y +CONFIG_MAC80211_LEDS=y +CONFIG_MAC80211_DEBUGFS=y +# CONFIG_MAC80211_DEBUG_MENU is not set +CONFIG_WIMAX=m +CONFIG_WIMAX_DEBUG_LEVEL=8 +CONFIG_RFKILL=m +CONFIG_RFKILL_LEDS=y +CONFIG_RFKILL_INPUT=y +CONFIG_NET_9P=m +CONFIG_NET_9P_RDMA=m +# CONFIG_NET_9P_DEBUG is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +# CONFIG_STANDALONE is not set +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +CONFIG_SYS_HYPERVISOR=y +CONFIG_CONNECTOR=y +CONFIG_PROC_EVENTS=y +CONFIG_MTD=m +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_TESTS=m +CONFIG_MTD_CONCAT=m +CONFIG_MTD_PARTITIONS=y +CONFIG_MTD_REDBOOT_PARTS=m +CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 +# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set +# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set +CONFIG_MTD_AR7_PARTS=m + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=m +CONFIG_HAVE_MTD_OTP=y +CONFIG_MTD_BLKDEVS=m +CONFIG_MTD_BLOCK=m +CONFIG_MTD_BLOCK_RO=m +CONFIG_FTL=m +CONFIG_NFTL=m +CONFIG_NFTL_RW=y +CONFIG_INFTL=m +CONFIG_RFD_FTL=m +CONFIG_SSFDC=m +CONFIG_MTD_OOPS=m + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=m +CONFIG_MTD_JEDECPROBE=m +CONFIG_MTD_GEN_PROBE=m +CONFIG_MTD_CFI_ADV_OPTIONS=y +CONFIG_MTD_CFI_NOSWAP=y +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set +CONFIG_MTD_CFI_GEOMETRY=y +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +CONFIG_MTD_MAP_BANK_WIDTH_8=y +CONFIG_MTD_MAP_BANK_WIDTH_16=y +CONFIG_MTD_MAP_BANK_WIDTH_32=y +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +CONFIG_MTD_CFI_I4=y +CONFIG_MTD_CFI_I8=y +CONFIG_MTD_OTP=y +CONFIG_MTD_CFI_INTELEXT=m +CONFIG_MTD_CFI_AMDSTD=m +CONFIG_MTD_CFI_STAA=m +CONFIG_MTD_CFI_UTIL=m +CONFIG_MTD_RAM=m +CONFIG_MTD_ROM=m +CONFIG_MTD_ABSENT=m + +# +# Mapping drivers for chip access +# +CONFIG_MTD_COMPLEX_MAPPINGS=y +CONFIG_MTD_PHYSMAP=m +CONFIG_MTD_PHYSMAP_COMPAT=y +CONFIG_MTD_PHYSMAP_START=0x8000000 +CONFIG_MTD_PHYSMAP_LEN=0 +CONFIG_MTD_PHYSMAP_BANKWIDTH=2 +CONFIG_MTD_SC520CDP=m +CONFIG_MTD_NETSC520=m +CONFIG_MTD_TS5500=m +CONFIG_MTD_SBC_GXX=m +CONFIG_MTD_AMD76XROM=m +CONFIG_MTD_ICHXROM=m +CONFIG_MTD_ESB2ROM=m +CONFIG_MTD_CK804XROM=m +CONFIG_MTD_SCB2_FLASH=m +CONFIG_MTD_NETtel=m +CONFIG_MTD_L440GX=m +CONFIG_MTD_PCI=m +CONFIG_MTD_GPIO_ADDR=m +CONFIG_MTD_INTEL_VR_NOR=m +CONFIG_MTD_PLATRAM=m + +# +# Self-contained MTD device drivers +# +CONFIG_MTD_PMC551=m +CONFIG_MTD_PMC551_BUGFIX=y +# CONFIG_MTD_PMC551_DEBUG is not set +CONFIG_MTD_DATAFLASH=m +CONFIG_MTD_DATAFLASH_WRITE_VERIFY=y +CONFIG_MTD_DATAFLASH_OTP=y +CONFIG_MTD_M25P80=m +CONFIG_M25PXX_USE_FAST_READ=y +CONFIG_MTD_SST25L=m +CONFIG_MTD_SLRAM=m +CONFIG_MTD_PHRAM=m +CONFIG_MTD_MTDRAM=m +CONFIG_MTDRAM_TOTAL_SIZE=4096 +CONFIG_MTDRAM_ERASE_SIZE=128 +CONFIG_MTD_BLOCK2MTD=m + +# +# Disk-On-Chip Device Drivers +# +CONFIG_MTD_DOC2000=m +CONFIG_MTD_DOC2001=m +CONFIG_MTD_DOC2001PLUS=m +CONFIG_MTD_DOCPROBE=m +CONFIG_MTD_DOCECC=m +CONFIG_MTD_DOCPROBE_ADVANCED=y +CONFIG_MTD_DOCPROBE_ADDRESS=0x0000 +CONFIG_MTD_DOCPROBE_HIGH=y +CONFIG_MTD_DOCPROBE_55AA=y +CONFIG_MTD_NAND=m +CONFIG_MTD_NAND_VERIFY_WRITE=y +CONFIG_MTD_NAND_ECC_SMC=y +CONFIG_MTD_NAND_MUSEUM_IDS=y +CONFIG_MTD_NAND_IDS=m +CONFIG_MTD_NAND_DISKONCHIP=m +CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED=y +CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0 +CONFIG_MTD_NAND_DISKONCHIP_PROBE_HIGH=y +CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE=y +CONFIG_MTD_NAND_CAFE=m +CONFIG_MTD_NAND_NANDSIM=m +CONFIG_MTD_NAND_PLATFORM=m +CONFIG_MTD_ALAUDA=m +CONFIG_MTD_ONENAND=m +CONFIG_MTD_ONENAND_VERIFY_WRITE=y +CONFIG_MTD_ONENAND_GENERIC=m +CONFIG_MTD_ONENAND_OTP=y +CONFIG_MTD_ONENAND_2X_PROGRAM=y +CONFIG_MTD_ONENAND_SIM=m + +# +# LPDDR flash memory drivers +# +CONFIG_MTD_LPDDR=m +CONFIG_MTD_QINFO_PROBE=m + +# +# UBI - Unsorted block images +# +CONFIG_MTD_UBI=m +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_MTD_UBI_BEB_RESERVE=1 +CONFIG_MTD_UBI_GLUEBI=m + +# +# UBI debugging options +# +# CONFIG_MTD_UBI_DEBUG is not set +CONFIG_PARPORT=m +CONFIG_PARPORT_PC=m +CONFIG_PARPORT_SERIAL=m +CONFIG_PARPORT_PC_FIFO=y +CONFIG_PARPORT_PC_SUPERIO=y +CONFIG_PARPORT_PC_PCMCIA=m +# CONFIG_PARPORT_GSC is not set +CONFIG_PARPORT_AX88796=m +CONFIG_PARPORT_1284=y +CONFIG_PARPORT_NOT_PC=y +CONFIG_PNP=y +# CONFIG_PNP_DEBUG_MESSAGES is not set + +# +# Protocols +# +CONFIG_PNPACPI=y +CONFIG_BLK_DEV=y +CONFIG_BLK_DEV_FD=m +CONFIG_PARIDE=m + +# +# Parallel IDE high-level drivers +# +CONFIG_PARIDE_PD=m +CONFIG_PARIDE_PCD=m +CONFIG_PARIDE_PF=m +CONFIG_PARIDE_PT=m +CONFIG_PARIDE_PG=m + +# +# Parallel IDE protocol modules +# +CONFIG_PARIDE_ATEN=m +CONFIG_PARIDE_BPCK=m +CONFIG_PARIDE_COMM=m +CONFIG_PARIDE_DSTR=m +CONFIG_PARIDE_FIT2=m +CONFIG_PARIDE_FIT3=m +CONFIG_PARIDE_EPAT=m +CONFIG_PARIDE_EPATC8=y +CONFIG_PARIDE_EPIA=m +CONFIG_PARIDE_FRIQ=m +CONFIG_PARIDE_FRPW=m +CONFIG_PARIDE_KBIC=m +CONFIG_PARIDE_KTTI=m +CONFIG_PARIDE_ON20=m +CONFIG_PARIDE_ON26=m +CONFIG_BLK_CPQ_DA=m +CONFIG_BLK_CPQ_CISS_DA=m +CONFIG_CISS_SCSI_TAPE=y +CONFIG_BLK_DEV_DAC960=m +CONFIG_BLK_DEV_UMEM=m +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_OSD=m +CONFIG_BLK_DEV_SX8=m +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=m +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=131072 +CONFIG_BLK_DEV_XIP=y +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +CONFIG_CDROM_PKTCDVD_WCACHE=y +CONFIG_ATA_OVER_ETH=m +# CONFIG_BLK_DEV_HD is not set +CONFIG_MISC_DEVICES=y +CONFIG_IBM_ASM=m +CONFIG_PHANTOM=m +CONFIG_SGI_IOC4=m +CONFIG_TIFM_CORE=m +CONFIG_TIFM_7XX1=m +CONFIG_ICS932S401=m +CONFIG_ENCLOSURE_SERVICES=m +CONFIG_HP_ILO=m +CONFIG_DELL_LAPTOP=m +# CONFIG_ISL29003 is not set +CONFIG_C2PORT=m +CONFIG_C2PORT_DURAMAR_2150=m + +# +# EEPROM support +# +CONFIG_EEPROM_AT24=m +CONFIG_EEPROM_AT25=m +CONFIG_EEPROM_LEGACY=m +CONFIG_EEPROM_MAX6875=m +CONFIG_EEPROM_93CX6=m +CONFIG_CB710_CORE=m +# CONFIG_CB710_DEBUG is not set +CONFIG_CB710_DEBUG_ASSUMPTIONS=y +CONFIG_HAVE_IDE=y +CONFIG_IDE=m + +# +# Please see Documentation/ide/ide.txt for help/info on IDE drives +# +CONFIG_IDE_XFER_MODE=y +CONFIG_IDE_TIMINGS=y +CONFIG_IDE_ATAPI=y +# CONFIG_BLK_DEV_IDE_SATA is not set +CONFIG_IDE_GD=m +CONFIG_IDE_GD_ATA=y +CONFIG_IDE_GD_ATAPI=y +CONFIG_BLK_DEV_IDECS=m +CONFIG_BLK_DEV_DELKIN=m +CONFIG_BLK_DEV_IDECD=m +CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y +CONFIG_BLK_DEV_IDETAPE=m +CONFIG_BLK_DEV_IDEACPI=y +# CONFIG_IDE_TASK_IOCTL is not set +CONFIG_IDE_PROC_FS=y + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=m +CONFIG_BLK_DEV_PLATFORM=m +CONFIG_BLK_DEV_CMD640=m +CONFIG_BLK_DEV_CMD640_ENHANCED=y +CONFIG_BLK_DEV_IDEPNP=m +CONFIG_BLK_DEV_IDEDMA_SFF=y + +# +# PCI IDE chipsets support +# +CONFIG_BLK_DEV_IDEPCI=y +CONFIG_BLK_DEV_OFFBOARD=y +CONFIG_BLK_DEV_GENERIC=m +CONFIG_BLK_DEV_OPTI621=m +CONFIG_BLK_DEV_RZ1000=m +CONFIG_BLK_DEV_IDEDMA_PCI=y +CONFIG_BLK_DEV_AEC62XX=m +CONFIG_BLK_DEV_ALI15X3=m +CONFIG_BLK_DEV_AMD74XX=m +CONFIG_BLK_DEV_ATIIXP=m +CONFIG_BLK_DEV_CMD64X=m +CONFIG_BLK_DEV_TRIFLEX=m +CONFIG_BLK_DEV_CS5520=m +CONFIG_BLK_DEV_CS5530=m +CONFIG_BLK_DEV_HPT366=m +CONFIG_BLK_DEV_JMICRON=m +CONFIG_BLK_DEV_SC1200=m +CONFIG_BLK_DEV_PIIX=m +CONFIG_BLK_DEV_IT8172=m +CONFIG_BLK_DEV_IT8213=m +CONFIG_BLK_DEV_IT821X=m +CONFIG_BLK_DEV_NS87415=m +CONFIG_BLK_DEV_PDC202XX_OLD=m +CONFIG_BLK_DEV_PDC202XX_NEW=m +CONFIG_BLK_DEV_SVWKS=m +CONFIG_BLK_DEV_SIIMAGE=m +CONFIG_BLK_DEV_SIS5513=m +CONFIG_BLK_DEV_SLC90E66=m +# CONFIG_BLK_DEV_TRM290 is not set +CONFIG_BLK_DEV_VIA82CXXX=m +CONFIG_BLK_DEV_TC86C001=m +CONFIG_BLK_DEV_IDEDMA=y + +# +# SCSI device support +# +CONFIG_RAID_ATTRS=m +CONFIG_SCSI=m +CONFIG_SCSI_DMA=y +CONFIG_SCSI_TGT=m +CONFIG_SCSI_NETLINK=y +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=m +CONFIG_CHR_DEV_ST=m +CONFIG_CHR_DEV_OSST=m +CONFIG_BLK_DEV_SR=m +# CONFIG_BLK_DEV_SR_VENDOR is not set +CONFIG_CHR_DEV_SG=m +CONFIG_CHR_DEV_SCH=m +CONFIG_SCSI_ENCLOSURE=m +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m + +# +# SCSI Transports +# +CONFIG_SCSI_SPI_ATTRS=m +CONFIG_SCSI_FC_ATTRS=m +CONFIG_SCSI_FC_TGT_ATTRS=y +CONFIG_SCSI_ISCSI_ATTRS=m +CONFIG_SCSI_SAS_ATTRS=m +CONFIG_SCSI_SAS_LIBSAS=m +CONFIG_SCSI_SAS_ATA=y +CONFIG_SCSI_SAS_HOST_SMP=y +# CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set +CONFIG_SCSI_SRP_ATTRS=m +CONFIG_SCSI_SRP_TGT_ATTRS=y +CONFIG_SCSI_LOWLEVEL=y +CONFIG_ISCSI_TCP=m +CONFIG_SCSI_CXGB3_ISCSI=m +CONFIG_SCSI_BNX2_ISCSI=m +CONFIG_BE2ISCSI=m +CONFIG_BLK_DEV_3W_XXXX_RAID=m +CONFIG_SCSI_3W_9XXX=m +CONFIG_SCSI_ACARD=m +CONFIG_SCSI_AACRAID=m +CONFIG_SCSI_AIC7XXX=m +CONFIG_AIC7XXX_CMDS_PER_DEVICE=32 +CONFIG_AIC7XXX_RESET_DELAY_MS=15000 +# CONFIG_AIC7XXX_DEBUG_ENABLE is not set +CONFIG_AIC7XXX_DEBUG_MASK=0 +CONFIG_AIC7XXX_REG_PRETTY_PRINT=y +CONFIG_SCSI_AIC7XXX_OLD=m +CONFIG_SCSI_AIC79XX=m +CONFIG_AIC79XX_CMDS_PER_DEVICE=32 +CONFIG_AIC79XX_RESET_DELAY_MS=5000 +# CONFIG_AIC79XX_DEBUG_ENABLE is not set +CONFIG_AIC79XX_DEBUG_MASK=0 +CONFIG_AIC79XX_REG_PRETTY_PRINT=y +CONFIG_SCSI_AIC94XX=m +# CONFIG_AIC94XX_DEBUG is not set +CONFIG_SCSI_MVSAS=m +# CONFIG_SCSI_MVSAS_DEBUG is not set +CONFIG_SCSI_DPT_I2O=m +CONFIG_SCSI_ADVANSYS=m +CONFIG_SCSI_ARCMSR=m +CONFIG_SCSI_ARCMSR_AER=y +CONFIG_MEGARAID_NEWGEN=y +CONFIG_MEGARAID_MM=m +CONFIG_MEGARAID_MAILBOX=m +CONFIG_MEGARAID_LEGACY=m +CONFIG_MEGARAID_SAS=m +CONFIG_SCSI_MPT2SAS=m +CONFIG_SCSI_MPT2SAS_MAX_SGE=128 +# CONFIG_SCSI_MPT2SAS_LOGGING is not set +CONFIG_SCSI_HPTIOP=m +CONFIG_SCSI_BUSLOGIC=m +CONFIG_LIBFC=m +CONFIG_LIBFCOE=m +CONFIG_FCOE=m +CONFIG_FCOE_FNIC=m +CONFIG_SCSI_DMX3191D=m +CONFIG_SCSI_EATA=m +CONFIG_SCSI_EATA_TAGGED_QUEUE=y +CONFIG_SCSI_EATA_LINKED_COMMANDS=y +CONFIG_SCSI_EATA_MAX_TAGS=16 +CONFIG_SCSI_FUTURE_DOMAIN=m +CONFIG_SCSI_GDTH=m +CONFIG_SCSI_IPS=m +CONFIG_SCSI_INITIO=m +CONFIG_SCSI_INIA100=m +CONFIG_SCSI_PPA=m +CONFIG_SCSI_IMM=m +# CONFIG_SCSI_IZIP_EPP16 is not set +# CONFIG_SCSI_IZIP_SLOW_CTR is not set +CONFIG_SCSI_STEX=m +CONFIG_SCSI_SYM53C8XX_2=m +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +CONFIG_SCSI_SYM53C8XX_MMIO=y +CONFIG_SCSI_IPR=m +CONFIG_SCSI_IPR_TRACE=y +CONFIG_SCSI_IPR_DUMP=y +CONFIG_SCSI_QLOGIC_1280=m +CONFIG_SCSI_QLA_FC=m +CONFIG_SCSI_QLA_ISCSI=m +CONFIG_SCSI_LPFC=m +# CONFIG_SCSI_LPFC_DEBUG_FS is not set +CONFIG_SCSI_DC395x=m +CONFIG_SCSI_DC390T=m +CONFIG_SCSI_DEBUG=m +CONFIG_SCSI_PMCRAID=m +CONFIG_SCSI_SRP=m +CONFIG_SCSI_BFA_FC=m +CONFIG_SCSI_LOWLEVEL_PCMCIA=y +CONFIG_PCMCIA_FDOMAIN=m +CONFIG_PCMCIA_QLOGIC=m +CONFIG_PCMCIA_SYM53C500=m +CONFIG_SCSI_DH=m +CONFIG_SCSI_DH_RDAC=m +CONFIG_SCSI_DH_HP_SW=m +CONFIG_SCSI_DH_EMC=m +CONFIG_SCSI_DH_ALUA=m +CONFIG_SCSI_OSD_INITIATOR=m +CONFIG_SCSI_OSD_ULD=m +CONFIG_SCSI_OSD_DPRINT_SENSE=1 +# CONFIG_SCSI_OSD_DEBUG is not set +CONFIG_ATA=m +# CONFIG_ATA_NONSTANDARD is not set +CONFIG_ATA_VERBOSE_ERROR=y +CONFIG_ATA_ACPI=y +CONFIG_SATA_PMP=y +CONFIG_SATA_AHCI=m +CONFIG_SATA_SIL24=m +CONFIG_ATA_SFF=y +CONFIG_SATA_SVW=m +CONFIG_ATA_PIIX=m +CONFIG_SATA_MV=m +CONFIG_SATA_NV=m +CONFIG_PDC_ADMA=m +CONFIG_SATA_QSTOR=m +CONFIG_SATA_PROMISE=m +CONFIG_SATA_SX4=m +CONFIG_SATA_SIL=m +CONFIG_SATA_SIS=m +CONFIG_SATA_ULI=m +CONFIG_SATA_VIA=m +CONFIG_SATA_VITESSE=m +CONFIG_SATA_INIC162X=m +CONFIG_PATA_ACPI=m +CONFIG_PATA_ALI=m +CONFIG_PATA_AMD=m +CONFIG_PATA_ARTOP=m +CONFIG_PATA_ATP867X=m +CONFIG_PATA_ATIIXP=m +CONFIG_PATA_CMD640_PCI=m +CONFIG_PATA_CMD64X=m +CONFIG_PATA_CS5520=m +CONFIG_PATA_CS5530=m +CONFIG_PATA_CYPRESS=m +CONFIG_PATA_EFAR=m +CONFIG_ATA_GENERIC=m +CONFIG_PATA_HPT366=m +CONFIG_PATA_HPT37X=m +CONFIG_PATA_HPT3X2N=m +CONFIG_PATA_HPT3X3=m +# CONFIG_PATA_HPT3X3_DMA is not set +CONFIG_PATA_IT821X=m +CONFIG_PATA_IT8213=m +CONFIG_PATA_JMICRON=m +CONFIG_PATA_TRIFLEX=m +CONFIG_PATA_MARVELL=m +CONFIG_PATA_MPIIX=m +CONFIG_PATA_OLDPIIX=m +CONFIG_PATA_NETCELL=m +CONFIG_PATA_NINJA32=m +CONFIG_PATA_NS87410=m +CONFIG_PATA_NS87415=m +CONFIG_PATA_OPTI=m +CONFIG_PATA_OPTIDMA=m +CONFIG_PATA_PCMCIA=m +CONFIG_PATA_PDC_OLD=m +CONFIG_PATA_RADISYS=m +CONFIG_PATA_RDC=m +CONFIG_PATA_RZ1000=m +CONFIG_PATA_SC1200=m +CONFIG_PATA_SERVERWORKS=m +CONFIG_PATA_PDC2027X=m +CONFIG_PATA_SIL680=m +CONFIG_PATA_SIS=m +CONFIG_PATA_VIA=m +CONFIG_PATA_WINBOND=m +CONFIG_PATA_SCH=m +CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_AUTODETECT=y +CONFIG_MD_LINEAR=m +CONFIG_MD_RAID0=m +CONFIG_MD_RAID1=m +CONFIG_MD_RAID10=m +CONFIG_MD_RAID456=m +# CONFIG_MULTICORE_RAID456 is not set +CONFIG_MD_RAID6_PQ=m +CONFIG_ASYNC_RAID6_TEST=m +CONFIG_MD_MULTIPATH=m +CONFIG_MD_FAULTY=m +CONFIG_BLK_DEV_DM=m +# CONFIG_DM_DEBUG is not set +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_MIRROR=m +CONFIG_DM_LOG_USERSPACE=m +CONFIG_DM_ZERO=m +CONFIG_DM_MULTIPATH=m +CONFIG_DM_MULTIPATH_QL=m +CONFIG_DM_MULTIPATH_ST=m +CONFIG_DM_DELAY=m +CONFIG_DM_UEVENT=y +CONFIG_FUSION=y +CONFIG_FUSION_SPI=m +CONFIG_FUSION_FC=m +CONFIG_FUSION_SAS=m +CONFIG_FUSION_MAX_SGE=128 +CONFIG_FUSION_CTL=m +CONFIG_FUSION_LAN=m +# CONFIG_FUSION_LOGGING is not set + +# +# IEEE 1394 (FireWire) support +# + +# +# You can enable one or both FireWire driver stacks. +# + +# +# See the help texts for more information. +# +# CONFIG_FIREWIRE is not set +CONFIG_IEEE1394=m +CONFIG_IEEE1394_OHCI1394=m +CONFIG_IEEE1394_PCILYNX=m +CONFIG_IEEE1394_SBP2=m +# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set +CONFIG_IEEE1394_ETH1394_ROM_ENTRY=y +CONFIG_IEEE1394_ETH1394=m +CONFIG_IEEE1394_RAWIO=m +CONFIG_IEEE1394_VIDEO1394=m +CONFIG_IEEE1394_DV1394=m +# CONFIG_IEEE1394_VERBOSEDEBUG is not set +CONFIG_I2O=m +CONFIG_I2O_LCT_NOTIFY_ON_CHANGES=y +CONFIG_I2O_EXT_ADAPTEC=y +CONFIG_I2O_EXT_ADAPTEC_DMA64=y +CONFIG_I2O_CONFIG=m +CONFIG_I2O_CONFIG_OLD_IOCTL=y +CONFIG_I2O_BUS=m +CONFIG_I2O_BLOCK=m +CONFIG_I2O_SCSI=m +CONFIG_I2O_PROC=m +# CONFIG_MACINTOSH_DRIVERS is not set +CONFIG_NETDEVICES=y +CONFIG_IFB=m +CONFIG_DUMMY=m +CONFIG_BONDING=m +CONFIG_MACVLAN=m +CONFIG_EQUALIZER=m +CONFIG_TUN=m +CONFIG_VETH=m +# CONFIG_NET_SB1000 is not set +CONFIG_ARCNET=m +CONFIG_ARCNET_1201=m +CONFIG_ARCNET_1051=m +CONFIG_ARCNET_RAW=m +CONFIG_ARCNET_CAP=m +CONFIG_ARCNET_COM90xx=m +CONFIG_ARCNET_COM90xxIO=m +CONFIG_ARCNET_RIM_I=m +# CONFIG_ARCNET_COM20020 is not set +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +CONFIG_MARVELL_PHY=m +CONFIG_DAVICOM_PHY=m +CONFIG_QSEMI_PHY=m +CONFIG_LXT_PHY=m +CONFIG_CICADA_PHY=m +CONFIG_VITESSE_PHY=m +CONFIG_SMSC_PHY=m +CONFIG_BROADCOM_PHY=m +CONFIG_ICPLUS_PHY=m +CONFIG_REALTEK_PHY=m +CONFIG_NATIONAL_PHY=m +CONFIG_STE10XP=m +CONFIG_LSI_ET1011C_PHY=m +CONFIG_FIXED_PHY=y +CONFIG_MDIO_BITBANG=m +CONFIG_MDIO_GPIO=m +CONFIG_NET_ETHERNET=y +CONFIG_MII=m +CONFIG_HAPPYMEAL=m +CONFIG_SUNGEM=m +CONFIG_CASSINI=m +CONFIG_NET_VENDOR_3COM=y +CONFIG_VORTEX=m +CONFIG_TYPHOON=m +CONFIG_ENC28J60=m +# CONFIG_ENC28J60_WRITEVERIFY is not set +CONFIG_ETHOC=m +CONFIG_DNET=m +CONFIG_NET_TULIP=y +CONFIG_DE2104X=m +CONFIG_DE2104X_DSL=0 +CONFIG_TULIP=m +# CONFIG_TULIP_MWI is not set +# CONFIG_TULIP_MMIO is not set +CONFIG_TULIP_NAPI=y +CONFIG_TULIP_NAPI_HW_MITIGATION=y +CONFIG_DE4X5=m +CONFIG_WINBOND_840=m +CONFIG_DM9102=m +CONFIG_ULI526X=m +CONFIG_PCMCIA_XIRCOM=m +CONFIG_HP100=m +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +CONFIG_NET_PCI=y +CONFIG_PCNET32=m +CONFIG_AMD8111_ETH=m +CONFIG_ADAPTEC_STARFIRE=m +CONFIG_B44=m +CONFIG_B44_PCI_AUTOSELECT=y +CONFIG_B44_PCICORE_AUTOSELECT=y +CONFIG_B44_PCI=y +CONFIG_FORCEDETH=m +CONFIG_FORCEDETH_NAPI=y +CONFIG_E100=m +CONFIG_FEALNX=m +CONFIG_NATSEMI=m +CONFIG_NE2K_PCI=m +CONFIG_8139CP=m +CONFIG_8139TOO=m +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +CONFIG_8139TOO_8129=y +# CONFIG_8139_OLD_RX_RESET is not set +CONFIG_R6040=m +CONFIG_SIS900=m +CONFIG_EPIC100=m +CONFIG_SMSC9420=m +CONFIG_SUNDANCE=m +# CONFIG_SUNDANCE_MMIO is not set +CONFIG_TLAN=m +CONFIG_KS8842=m +CONFIG_KS8851=m +CONFIG_KS8851_MLL=m +CONFIG_VIA_RHINE=m +CONFIG_VIA_RHINE_MMIO=y +CONFIG_SC92031=m +CONFIG_NET_POCKET=y +CONFIG_ATP=m +CONFIG_DE600=m +CONFIG_DE620=m +CONFIG_ATL2=m +CONFIG_NETDEV_1000=y +CONFIG_ACENIC=m +# CONFIG_ACENIC_OMIT_TIGON_I is not set +CONFIG_DL2K=m +CONFIG_E1000=m +CONFIG_E1000E=m +CONFIG_IP1000=m +CONFIG_IGB=m +CONFIG_IGB_DCA=y +CONFIG_IGBVF=m +CONFIG_NS83820=m +CONFIG_HAMACHI=m +CONFIG_YELLOWFIN=m +CONFIG_R8169=m +CONFIG_R8169_VLAN=y +CONFIG_SIS190=m +CONFIG_SKGE=m +# CONFIG_SKGE_DEBUG is not set +CONFIG_SKY2=m +# CONFIG_SKY2_DEBUG is not set +CONFIG_VIA_VELOCITY=m +CONFIG_TIGON3=m +CONFIG_BNX2=m +CONFIG_CNIC=m +CONFIG_QLA3XXX=m +CONFIG_ATL1=m +CONFIG_ATL1E=m +CONFIG_ATL1C=m +CONFIG_JME=m +CONFIG_NETDEV_10000=y +CONFIG_MDIO=m +CONFIG_CHELSIO_T1=m +CONFIG_CHELSIO_T1_1G=y +CONFIG_CHELSIO_T3_DEPENDS=y +CONFIG_CHELSIO_T3=m +CONFIG_ENIC=m +CONFIG_IXGBE=m +CONFIG_IXGBE_DCA=y +CONFIG_IXGBE_DCB=y +CONFIG_IXGB=m +CONFIG_S2IO=m +CONFIG_VXGE=m +# CONFIG_VXGE_DEBUG_TRACE_ALL is not set +CONFIG_MYRI10GE=m +CONFIG_MYRI10GE_DCA=y +CONFIG_NETXEN_NIC=m +CONFIG_NIU=m +CONFIG_MLX4_EN=m +CONFIG_MLX4_CORE=m +CONFIG_MLX4_DEBUG=y +CONFIG_TEHUTI=m +CONFIG_BNX2X=m +CONFIG_QLGE=m +CONFIG_SFC=m +CONFIG_SFC_DRIVERLINK=y +CONFIG_SFC_RESOURCE=m +CONFIG_SFC_MTD=y +CONFIG_BE2NET=m +CONFIG_TR=m +CONFIG_IBMOL=m +CONFIG_3C359=m +CONFIG_TMS380TR=m +CONFIG_TMSPCI=m +CONFIG_ABYSS=m +CONFIG_WLAN=y +CONFIG_WLAN_PRE80211=y +CONFIG_STRIP=m +CONFIG_PCMCIA_WAVELAN=m +CONFIG_PCMCIA_NETWAVE=m +CONFIG_WLAN_80211=y +CONFIG_PCMCIA_RAYCS=m +CONFIG_LIBERTAS=m +CONFIG_LIBERTAS_USB=m +CONFIG_LIBERTAS_CS=m +CONFIG_LIBERTAS_SDIO=m +CONFIG_LIBERTAS_SPI=m +# CONFIG_LIBERTAS_DEBUG is not set +CONFIG_LIBERTAS_THINFIRM=m +CONFIG_LIBERTAS_THINFIRM_USB=m +CONFIG_AIRO=m +CONFIG_ATMEL=m +CONFIG_PCI_ATMEL=m +CONFIG_PCMCIA_ATMEL=m +CONFIG_AT76C50X_USB=m +CONFIG_AIRO_CS=m +CONFIG_PCMCIA_WL3501=m +CONFIG_PRISM54=m +CONFIG_USB_ZD1201=m +CONFIG_USB_NET_RNDIS_WLAN=m +CONFIG_RTL8180=m +CONFIG_RTL8187=m +CONFIG_RTL8187_LEDS=y +CONFIG_ADM8211=m +CONFIG_MAC80211_HWSIM=m +CONFIG_MWL8K=m +CONFIG_P54_COMMON=m +CONFIG_P54_USB=m +CONFIG_P54_PCI=m +CONFIG_P54_SPI=m +CONFIG_P54_LEDS=y +CONFIG_ATH_COMMON=m +CONFIG_ATH5K=m +# CONFIG_ATH5K_DEBUG is not set +CONFIG_ATH9K=m +# CONFIG_ATH9K_DEBUG is not set +CONFIG_AR9170_USB=m +CONFIG_AR9170_LEDS=y +CONFIG_IPW2100=m +CONFIG_IPW2100_MONITOR=y +CONFIG_IPW2100_DEBUG=y +CONFIG_IPW2200=m +CONFIG_IPW2200_MONITOR=y +CONFIG_IPW2200_RADIOTAP=y +CONFIG_IPW2200_PROMISCUOUS=y +CONFIG_IPW2200_QOS=y +CONFIG_IPW2200_DEBUG=y +CONFIG_LIBIPW=m +CONFIG_LIBIPW_DEBUG=y +CONFIG_IWLWIFI=m +CONFIG_IWLWIFI_LEDS=y +CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT=y +CONFIG_IWLWIFI_DEBUG=y +CONFIG_IWLWIFI_DEBUGFS=y +CONFIG_IWLAGN=m +CONFIG_IWL4965=y +CONFIG_IWL5000=y +CONFIG_IWL3945=m +CONFIG_IWL3945_SPECTRUM_MEASUREMENT=y +CONFIG_HOSTAP=m +CONFIG_HOSTAP_FIRMWARE=y +CONFIG_HOSTAP_FIRMWARE_NVRAM=y +CONFIG_HOSTAP_PLX=m +CONFIG_HOSTAP_PCI=m +CONFIG_HOSTAP_CS=m +CONFIG_B43=m +CONFIG_B43_PCI_AUTOSELECT=y +CONFIG_B43_PCICORE_AUTOSELECT=y +CONFIG_B43_PCMCIA=y +CONFIG_B43_SDIO=y +CONFIG_B43_PIO=y +CONFIG_B43_PHY_LP=y +CONFIG_B43_LEDS=y +CONFIG_B43_HWRNG=y +# CONFIG_B43_DEBUG is not set +CONFIG_B43LEGACY=m +CONFIG_B43LEGACY_PCI_AUTOSELECT=y +CONFIG_B43LEGACY_PCICORE_AUTOSELECT=y +CONFIG_B43LEGACY_LEDS=y +CONFIG_B43LEGACY_HWRNG=y +# CONFIG_B43LEGACY_DEBUG is not set +CONFIG_B43LEGACY_DMA=y +CONFIG_B43LEGACY_PIO=y +CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y +# CONFIG_B43LEGACY_DMA_MODE is not set +# CONFIG_B43LEGACY_PIO_MODE is not set +CONFIG_ZD1211RW=m +# CONFIG_ZD1211RW_DEBUG is not set +CONFIG_RT2X00=m +CONFIG_RT2400PCI=m +CONFIG_RT2500PCI=m +CONFIG_RT61PCI=m +CONFIG_RT2500USB=m +CONFIG_RT73USB=m +CONFIG_RT2800USB=m +CONFIG_RT2X00_LIB_PCI=m +CONFIG_RT2X00_LIB_USB=m +CONFIG_RT2X00_LIB=m +CONFIG_RT2X00_LIB_HT=y +CONFIG_RT2X00_LIB_FIRMWARE=y +CONFIG_RT2X00_LIB_CRYPTO=y +CONFIG_RT2X00_LIB_LEDS=y +# CONFIG_RT2X00_LIB_DEBUGFS is not set +# CONFIG_RT2X00_DEBUG is not set +CONFIG_HERMES=m +CONFIG_HERMES_CACHE_FW_ON_INIT=y +CONFIG_PLX_HERMES=m +CONFIG_TMD_HERMES=m +CONFIG_NORTEL_HERMES=m +CONFIG_PCI_HERMES=m +CONFIG_PCMCIA_HERMES=m +CONFIG_PCMCIA_SPECTRUM=m +CONFIG_WL12XX=m +CONFIG_WL1251=m +CONFIG_WL1251_SPI=m +CONFIG_WL1251_SDIO=m +CONFIG_WL1271=m +CONFIG_IWM=m +# CONFIG_IWM_DEBUG is not set + +# +# WiMAX Wireless Broadband devices +# +CONFIG_WIMAX_I2400M=m +CONFIG_WIMAX_I2400M_USB=m +CONFIG_WIMAX_I2400M_SDIO=m +CONFIG_WIMAX_I2400M_DEBUG_LEVEL=8 + +# +# USB Network Adapters +# +CONFIG_USB_CATC=m +CONFIG_USB_KAWETH=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_USBNET=m +CONFIG_USB_NET_AX8817X=m +CONFIG_USB_NET_CDCETHER=m +CONFIG_USB_NET_CDC_EEM=m +CONFIG_USB_NET_DM9601=m +CONFIG_USB_NET_SMSC95XX=m +CONFIG_USB_NET_GL620A=m +CONFIG_USB_NET_NET1080=m +CONFIG_USB_NET_PLUSB=m +CONFIG_USB_NET_MCS7830=m +CONFIG_USB_NET_RNDIS_HOST=m +CONFIG_USB_NET_CDC_SUBSET=m +CONFIG_USB_ALI_M5632=y +CONFIG_USB_AN2720=y +CONFIG_USB_BELKIN=y +CONFIG_USB_ARMLINUX=y +CONFIG_USB_EPSON2888=y +CONFIG_USB_KC2190=y +CONFIG_USB_NET_ZAURUS=m +CONFIG_USB_HSO=m +CONFIG_USB_NET_INT51X1=m +CONFIG_USB_CDC_PHONET=m +CONFIG_NET_PCMCIA=y +CONFIG_PCMCIA_3C589=m +CONFIG_PCMCIA_3C574=m +CONFIG_PCMCIA_FMVJ18X=m +CONFIG_PCMCIA_PCNET=m +CONFIG_PCMCIA_NMCLAN=m +CONFIG_PCMCIA_SMC91C92=m +CONFIG_PCMCIA_XIRC2PS=m +CONFIG_PCMCIA_AXNET=m +CONFIG_PCMCIA_IBMTR=m +CONFIG_WAN=y +CONFIG_LANMEDIA=m +CONFIG_HDLC=m +CONFIG_HDLC_RAW=m +CONFIG_HDLC_RAW_ETH=m +CONFIG_HDLC_CISCO=m +CONFIG_HDLC_FR=m +CONFIG_HDLC_PPP=m +CONFIG_HDLC_X25=m +CONFIG_PCI200SYN=m +CONFIG_WANXL=m +CONFIG_PC300TOO=m +CONFIG_FARSYNC=m +CONFIG_DSCC4=m +CONFIG_DSCC4_PCISYNC=y +CONFIG_DSCC4_PCI_RST=y +CONFIG_DLCI=m +CONFIG_DLCI_MAX=8 +# CONFIG_WAN_ROUTER_DRIVERS is not set +CONFIG_LAPBETHER=m +CONFIG_X25_ASY=m +CONFIG_SBNI=m +CONFIG_SBNI_MULTILINE=y +CONFIG_ATM_DRIVERS=y +CONFIG_ATM_DUMMY=m +CONFIG_ATM_TCP=m +CONFIG_ATM_LANAI=m +CONFIG_ATM_ENI=m +# CONFIG_ATM_ENI_DEBUG is not set +CONFIG_ATM_ENI_TUNE_BURST=y +CONFIG_ATM_ENI_BURST_TX_16W=y +CONFIG_ATM_ENI_BURST_TX_8W=y +CONFIG_ATM_ENI_BURST_TX_4W=y +CONFIG_ATM_ENI_BURST_TX_2W=y +CONFIG_ATM_ENI_BURST_RX_16W=y +CONFIG_ATM_ENI_BURST_RX_8W=y +CONFIG_ATM_ENI_BURST_RX_4W=y +CONFIG_ATM_ENI_BURST_RX_2W=y +CONFIG_ATM_FIRESTREAM=m +CONFIG_ATM_ZATM=m +# CONFIG_ATM_ZATM_DEBUG is not set +CONFIG_ATM_IDT77252=m +# CONFIG_ATM_IDT77252_DEBUG is not set +# CONFIG_ATM_IDT77252_RCV_ALL is not set +CONFIG_ATM_IDT77252_USE_SUNI=y +CONFIG_ATM_AMBASSADOR=m +# CONFIG_ATM_AMBASSADOR_DEBUG is not set +CONFIG_ATM_HORIZON=m +# CONFIG_ATM_HORIZON_DEBUG is not set +CONFIG_ATM_IA=m +# CONFIG_ATM_IA_DEBUG is not set +CONFIG_ATM_FORE200E=m +CONFIG_ATM_FORE200E_USE_TASKLET=y +CONFIG_ATM_FORE200E_TX_RETRY=16 +CONFIG_ATM_FORE200E_DEBUG=0 +CONFIG_ATM_HE=m +CONFIG_ATM_HE_USE_SUNI=y +CONFIG_ATM_SOLOS=m +CONFIG_IEEE802154_DRIVERS=m +CONFIG_IEEE802154_FAKEHARD=m +CONFIG_FDDI=m +CONFIG_DEFXX=m +CONFIG_DEFXX_MMIO=y +CONFIG_SKFP=m +CONFIG_HIPPI=y +CONFIG_ROADRUNNER=m +CONFIG_ROADRUNNER_LARGE_RINGS=y +CONFIG_PLIP=m +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPP_MPPE=m +CONFIG_PPPOE=m +CONFIG_PPPOATM=m +CONFIG_PPPOL2TP=m +CONFIG_SLIP=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLHC=m +CONFIG_SLIP_SMART=y +CONFIG_SLIP_MODE_SLIP6=y +CONFIG_NET_FC=y +CONFIG_NETCONSOLE=m +CONFIG_NETCONSOLE_DYNAMIC=y +CONFIG_NETPOLL=y +CONFIG_NETPOLL_TRAP=y +CONFIG_NET_POLL_CONTROLLER=y +CONFIG_ISDN=y +CONFIG_ISDN_I4L=m +CONFIG_MISDN=m +CONFIG_MISDN_DSP=m +CONFIG_MISDN_L1OIP=m + +# +# mISDN hardware drivers +# +CONFIG_MISDN_HFCPCI=m +CONFIG_MISDN_HFCMULTI=m +CONFIG_MISDN_HFCUSB=m +CONFIG_MISDN_AVMFRITZ=m +CONFIG_MISDN_SPEEDFAX=m +CONFIG_MISDN_INFINEON=m +CONFIG_MISDN_W6692=m +CONFIG_MISDN_NETJET=m +CONFIG_MISDN_IPAC=m +CONFIG_MISDN_ISAR=m +CONFIG_ISDN_PPP=y +CONFIG_ISDN_PPP_VJ=y +CONFIG_ISDN_MPP=y +CONFIG_IPPP_FILTER=y +CONFIG_ISDN_PPP_BSDCOMP=m +CONFIG_ISDN_AUDIO=y +CONFIG_ISDN_TTY_FAX=y +CONFIG_ISDN_X25=y + +# +# ISDN feature submodules +# +CONFIG_ISDN_DIVERSION=m + +# +# ISDN4Linux hardware drivers +# + +# +# Passive cards +# +CONFIG_ISDN_DRV_HISAX=m + +# +# D-channel protocol features +# +CONFIG_HISAX_EURO=y +CONFIG_DE_AOC=y +# CONFIG_HISAX_NO_SENDCOMPLETE is not set +# CONFIG_HISAX_NO_LLC is not set +# CONFIG_HISAX_NO_KEYPAD is not set +CONFIG_HISAX_1TR6=y +CONFIG_HISAX_NI1=y +CONFIG_HISAX_MAX_CARDS=8 + +# +# HiSax supported cards +# +CONFIG_HISAX_16_3=y +CONFIG_HISAX_TELESPCI=y +CONFIG_HISAX_S0BOX=y +CONFIG_HISAX_FRITZPCI=y +CONFIG_HISAX_AVM_A1_PCMCIA=y +CONFIG_HISAX_ELSA=y +CONFIG_HISAX_DIEHLDIVA=y +CONFIG_HISAX_SEDLBAUER=y +CONFIG_HISAX_NETJET=y +CONFIG_HISAX_NETJET_U=y +CONFIG_HISAX_NICCY=y +CONFIG_HISAX_BKM_A4T=y +CONFIG_HISAX_SCT_QUADRO=y +CONFIG_HISAX_GAZEL=y +CONFIG_HISAX_HFC_PCI=y +CONFIG_HISAX_W6692=y +CONFIG_HISAX_HFC_SX=y +CONFIG_HISAX_ENTERNOW_PCI=y +# CONFIG_HISAX_DEBUG is not set + +# +# HiSax PCMCIA card service modules +# +CONFIG_HISAX_SEDLBAUER_CS=m +CONFIG_HISAX_ELSA_CS=m +CONFIG_HISAX_AVM_A1_CS=m +CONFIG_HISAX_TELES_CS=m + +# +# HiSax sub driver modules +# +CONFIG_HISAX_ST5481=m +CONFIG_HISAX_HFCUSB=m +CONFIG_HISAX_HFC4S8S=m +CONFIG_HISAX_FRITZ_PCIPNP=m + +# +# Active cards +# +CONFIG_HYSDN=m +CONFIG_HYSDN_CAPI=y +CONFIG_ISDN_HDLC=m +CONFIG_ISDN_CAPI=m +CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y +CONFIG_CAPI_TRACE=y +CONFIG_ISDN_CAPI_MIDDLEWARE=y +CONFIG_ISDN_CAPI_CAPI20=m +CONFIG_ISDN_CAPI_CAPIFS_BOOL=y +CONFIG_ISDN_CAPI_CAPIFS=m +CONFIG_ISDN_CAPI_CAPIDRV=m + +# +# CAPI hardware drivers +# +CONFIG_CAPI_AVM=y +CONFIG_ISDN_DRV_AVMB1_B1PCI=m +CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y +CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m +CONFIG_ISDN_DRV_AVMB1_AVM_CS=m +CONFIG_ISDN_DRV_AVMB1_T1PCI=m +CONFIG_ISDN_DRV_AVMB1_C4=m +CONFIG_CAPI_EICON=y +CONFIG_ISDN_DIVAS=m +CONFIG_ISDN_DIVAS_BRIPCI=y +CONFIG_ISDN_DIVAS_PRIPCI=y +CONFIG_ISDN_DIVAS_DIVACAPI=m +CONFIG_ISDN_DIVAS_USERIDI=m +CONFIG_ISDN_DIVAS_MAINT=m +CONFIG_ISDN_DRV_GIGASET=m +CONFIG_GIGASET_BASE=m +CONFIG_GIGASET_M105=m +CONFIG_GIGASET_M101=m +# CONFIG_GIGASET_DEBUG is not set +CONFIG_PHONE=m +CONFIG_PHONE_IXJ=m +CONFIG_PHONE_IXJ_PCMCIA=m + +# +# Input device support +# +CONFIG_INPUT=y +CONFIG_INPUT_FF_MEMLESS=m +CONFIG_INPUT_POLLDEV=m + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +CONFIG_INPUT_JOYDEV=m +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ADP5588=m +CONFIG_KEYBOARD_ATKBD=y +CONFIG_QT2160=m +# CONFIG_KEYBOARD_LKKBD is not set +CONFIG_KEYBOARD_GPIO=m +CONFIG_KEYBOARD_MATRIX=m +CONFIG_KEYBOARD_LM8323=m +CONFIG_KEYBOARD_MAX7359=m +CONFIG_KEYBOARD_NEWTON=m +CONFIG_KEYBOARD_OPENCORES=m +# CONFIG_KEYBOARD_STOWAWAY is not set +CONFIG_KEYBOARD_SUNKBD=m +CONFIG_KEYBOARD_XTKBD=m +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_PS2_ALPS=y +CONFIG_MOUSE_PS2_LOGIPS2PP=y +CONFIG_MOUSE_PS2_SYNAPTICS=y +CONFIG_MOUSE_PS2_LIFEBOOK=y +CONFIG_MOUSE_PS2_TRACKPOINT=y +CONFIG_MOUSE_PS2_ELANTECH=y +CONFIG_MOUSE_PS2_SENTELIC=y +CONFIG_MOUSE_PS2_TOUCHKIT=y +CONFIG_MOUSE_SERIAL=m +CONFIG_MOUSE_APPLETOUCH=m +CONFIG_MOUSE_BCM5974=m +CONFIG_MOUSE_VSXXXAA=m +CONFIG_MOUSE_GPIO=m +CONFIG_MOUSE_SYNAPTICS_I2C=m +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_ANALOG=m +CONFIG_JOYSTICK_A3D=m +CONFIG_JOYSTICK_ADI=m +CONFIG_JOYSTICK_COBRA=m +CONFIG_JOYSTICK_GF2K=m +CONFIG_JOYSTICK_GRIP=m +CONFIG_JOYSTICK_GRIP_MP=m +CONFIG_JOYSTICK_GUILLEMOT=m +CONFIG_JOYSTICK_INTERACT=m +CONFIG_JOYSTICK_SIDEWINDER=m +CONFIG_JOYSTICK_TMDC=m +CONFIG_JOYSTICK_IFORCE=m +CONFIG_JOYSTICK_IFORCE_USB=y +CONFIG_JOYSTICK_IFORCE_232=y +CONFIG_JOYSTICK_WARRIOR=m +CONFIG_JOYSTICK_MAGELLAN=m +CONFIG_JOYSTICK_SPACEORB=m +CONFIG_JOYSTICK_SPACEBALL=m +CONFIG_JOYSTICK_STINGER=m +CONFIG_JOYSTICK_TWIDJOY=m +CONFIG_JOYSTICK_ZHENHUA=m +CONFIG_JOYSTICK_DB9=m +CONFIG_JOYSTICK_GAMECON=m +CONFIG_JOYSTICK_TURBOGRAFX=m +CONFIG_JOYSTICK_JOYDUMP=m +CONFIG_JOYSTICK_XPAD=m +CONFIG_JOYSTICK_XPAD_FF=y +CONFIG_JOYSTICK_XPAD_LEDS=y +CONFIG_INPUT_TABLET=y +CONFIG_TABLET_USB_ACECAD=m +CONFIG_TABLET_USB_AIPTEK=m +CONFIG_TABLET_USB_GTCO=m +CONFIG_TABLET_USB_KBTAB=m +CONFIG_TABLET_USB_WACOM=m +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_ADS7846=m +CONFIG_TOUCHSCREEN_AD7877=m +CONFIG_TOUCHSCREEN_AD7879_I2C=m +CONFIG_TOUCHSCREEN_AD7879=m +CONFIG_TOUCHSCREEN_EETI=m +CONFIG_TOUCHSCREEN_FUJITSU=m +CONFIG_TOUCHSCREEN_GUNZE=m +CONFIG_TOUCHSCREEN_ELO=m +CONFIG_TOUCHSCREEN_WACOM_W8001=m +CONFIG_TOUCHSCREEN_MCS5000=m +CONFIG_TOUCHSCREEN_MTOUCH=m +CONFIG_TOUCHSCREEN_INEXIO=m +CONFIG_TOUCHSCREEN_MK712=m +CONFIG_TOUCHSCREEN_PENMOUNT=m +CONFIG_TOUCHSCREEN_TOUCHRIGHT=m +CONFIG_TOUCHSCREEN_TOUCHWIN=m +CONFIG_TOUCHSCREEN_UCB1400=m +CONFIG_TOUCHSCREEN_WM97XX=m +CONFIG_TOUCHSCREEN_WM9705=y +CONFIG_TOUCHSCREEN_WM9712=y +CONFIG_TOUCHSCREEN_WM9713=y +CONFIG_TOUCHSCREEN_USB_COMPOSITE=m +CONFIG_TOUCHSCREEN_USB_EGALAX=y +CONFIG_TOUCHSCREEN_USB_PANJIT=y +CONFIG_TOUCHSCREEN_USB_3M=y +CONFIG_TOUCHSCREEN_USB_ITM=y +CONFIG_TOUCHSCREEN_USB_ETURBO=y +CONFIG_TOUCHSCREEN_USB_GUNZE=y +CONFIG_TOUCHSCREEN_USB_DMC_TSC10=y +CONFIG_TOUCHSCREEN_USB_IRTOUCH=y +CONFIG_TOUCHSCREEN_USB_IDEALTEK=y +CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH=y +CONFIG_TOUCHSCREEN_USB_GOTOP=y +CONFIG_TOUCHSCREEN_USB_JASTEC=y +CONFIG_TOUCHSCREEN_USB_E2I=y +CONFIG_TOUCHSCREEN_TOUCHIT213=m +CONFIG_TOUCHSCREEN_TSC2007=m +CONFIG_TOUCHSCREEN_PCAP=m +CONFIG_INPUT_MISC=y +CONFIG_INPUT_PCSPKR=m +CONFIG_INPUT_APANEL=m +CONFIG_INPUT_ATLAS_BTNS=m +CONFIG_INPUT_ATI_REMOTE=m +CONFIG_INPUT_ATI_REMOTE2=m +CONFIG_INPUT_KEYSPAN_REMOTE=m +CONFIG_INPUT_POWERMATE=m +CONFIG_INPUT_YEALINK=m +CONFIG_INPUT_CM109=m +CONFIG_INPUT_UINPUT=m +CONFIG_INPUT_WINBOND_CIR=m +CONFIG_INPUT_GPIO_ROTARY_ENCODER=m +CONFIG_INPUT_PCAP=m + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=m +CONFIG_SERIO_CT82C710=m +CONFIG_SERIO_PARKBD=m +CONFIG_SERIO_PCIPS2=m +CONFIG_SERIO_LIBPS2=y +CONFIG_SERIO_RAW=m +CONFIG_GAMEPORT=m +CONFIG_GAMEPORT_NS558=m +CONFIG_GAMEPORT_L4=m +CONFIG_GAMEPORT_EMU10K1=m +CONFIG_GAMEPORT_FM801=m + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_DEVKMEM=y +CONFIG_SERIAL_NONSTANDARD=y +CONFIG_COMPUTONE=m +CONFIG_ROCKETPORT=m +CONFIG_CYCLADES=m +# CONFIG_CYZ_INTR is not set +CONFIG_DIGIEPCA=m +CONFIG_MOXA_INTELLIO=m +CONFIG_MOXA_SMARTIO=m +CONFIG_ISI=m +CONFIG_SYNCLINK=m +CONFIG_SYNCLINKMP=m +CONFIG_SYNCLINK_GT=m +CONFIG_N_HDLC=m +CONFIG_RISCOM8=m +CONFIG_SPECIALIX=m +CONFIG_STALDRV=y +CONFIG_STALLION=m +CONFIG_ISTALLION=m +CONFIG_NOZOMI=m + +# +# Serial drivers +# +CONFIG_SERIAL_8250=m +CONFIG_FIX_EARLYCON_MEM=y +CONFIG_SERIAL_8250_PCI=m +CONFIG_SERIAL_8250_PNP=m +CONFIG_SERIAL_8250_CS=m +CONFIG_SERIAL_8250_NR_UARTS=16 +CONFIG_SERIAL_8250_RUNTIME_UARTS=8 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_MAX3100 is not set +CONFIG_SERIAL_CORE=m +CONFIG_SERIAL_JSM=m +CONFIG_UNIX98_PTYS=y +CONFIG_DEVPTS_MULTIPLE_INSTANCES=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=0 +CONFIG_PRINTER=m +# CONFIG_LP_CONSOLE is not set +CONFIG_PPDEV=m +CONFIG_IPMI_HANDLER=m +CONFIG_IPMI_PANIC_EVENT=y +# CONFIG_IPMI_PANIC_STRING is not set +CONFIG_IPMI_DEVICE_INTERFACE=m +CONFIG_IPMI_SI=m +CONFIG_IPMI_WATCHDOG=m +CONFIG_IPMI_POWEROFF=m +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_TIMERIOMEM=m +CONFIG_HW_RANDOM_INTEL=m +CONFIG_HW_RANDOM_AMD=m +CONFIG_HW_RANDOM_VIA=m +CONFIG_NVRAM=y +CONFIG_R3964=m +CONFIG_APPLICOM=m + +# +# PCMCIA character devices +# +CONFIG_SYNCLINK_CS=m +CONFIG_CARDMAN_4000=m +CONFIG_CARDMAN_4040=m +CONFIG_IPWIRELESS=m +CONFIG_MWAVE=m +CONFIG_PC8736x_GPIO=m +CONFIG_NSC_GPIO=m +CONFIG_RAW_DRIVER=m +CONFIG_MAX_RAW_DEVS=4096 +CONFIG_HANGCHECK_TIMER=m +CONFIG_TCG_TPM=m +CONFIG_TCG_TIS=m +CONFIG_TCG_NSC=m +CONFIG_TCG_ATMEL=m +CONFIG_TCG_INFINEON=m +CONFIG_TCG_XEN=m +CONFIG_TELCLOCK=m +CONFIG_DEVPORT=y +CONFIG_I2C=m +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_COMPAT=y +CONFIG_I2C_CHARDEV=m +CONFIG_I2C_HELPER_AUTO=y +CONFIG_I2C_ALGOBIT=m +CONFIG_I2C_ALGOPCA=m + +# +# I2C Hardware Bus support +# + +# +# PC SMBus host controller drivers +# +CONFIG_I2C_ALI1535=m +CONFIG_I2C_ALI1563=m +CONFIG_I2C_ALI15X3=m +CONFIG_I2C_AMD756=m +CONFIG_I2C_AMD756_S4882=m +CONFIG_I2C_AMD8111=m +CONFIG_I2C_I801=m +CONFIG_I2C_ISCH=m +CONFIG_I2C_PIIX4=m +CONFIG_I2C_NFORCE2=m +CONFIG_I2C_NFORCE2_S4985=m +CONFIG_I2C_SIS5595=m +CONFIG_I2C_SIS630=m +CONFIG_I2C_SIS96X=m +CONFIG_I2C_VIA=m +CONFIG_I2C_VIAPRO=m + +# +# ACPI drivers +# +CONFIG_I2C_SCMI=m + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +CONFIG_I2C_GPIO=m +CONFIG_I2C_OCORES=m +# CONFIG_I2C_SIMTEC is not set + +# +# External I2C/SMBus adapter drivers +# +CONFIG_I2C_PARPORT=m +CONFIG_I2C_PARPORT_LIGHT=m +CONFIG_I2C_TAOS_EVM=m +CONFIG_I2C_TINY_USB=m + +# +# Graphics adapter I2C/DDC channel drivers +# +# CONFIG_I2C_VOODOO3 is not set + +# +# Other I2C/SMBus bus drivers +# +CONFIG_I2C_PCA_PLATFORM=m +CONFIG_I2C_STUB=m + +# +# Miscellaneous I2C Chip support +# +CONFIG_DS1682=m +CONFIG_SENSORS_TSL2550=m +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +CONFIG_SPI_BITBANG=m +CONFIG_SPI_BUTTERFLY=m +CONFIG_SPI_GPIO=m +CONFIG_SPI_LM70_LLP=m + +# +# SPI Protocol Masters +# +CONFIG_SPI_SPIDEV=m +CONFIG_SPI_TLE62X0=m + +# +# PPS support +# +CONFIG_PPS=m +# CONFIG_PPS_DEBUG is not set +CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y +CONFIG_GPIOLIB=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO expanders: +# + +# +# I2C GPIO expanders: +# +CONFIG_GPIO_MAX732X=m +CONFIG_GPIO_PCA953X=m +CONFIG_GPIO_PCF857X=m + +# +# PCI GPIO expanders: +# +CONFIG_GPIO_LANGWELL=y + +# +# SPI GPIO expanders: +# +CONFIG_GPIO_MAX7301=m +CONFIG_GPIO_MCP23S08=m +CONFIG_GPIO_MC33880=m + +# +# AC97 GPIO expanders: +# +CONFIG_GPIO_UCB1400=y +CONFIG_W1=m +CONFIG_W1_CON=y + +# +# 1-wire Bus Masters +# +CONFIG_W1_MASTER_MATROX=m +CONFIG_W1_MASTER_DS2490=m +CONFIG_W1_MASTER_DS2482=m +CONFIG_W1_MASTER_GPIO=m + +# +# 1-wire Slaves +# +CONFIG_W1_SLAVE_THERM=m +CONFIG_W1_SLAVE_SMEM=m +CONFIG_W1_SLAVE_DS2431=m +CONFIG_W1_SLAVE_DS2433=m +CONFIG_W1_SLAVE_DS2433_CRC=y +CONFIG_W1_SLAVE_DS2760=m +CONFIG_W1_SLAVE_BQ27000=m +CONFIG_POWER_SUPPLY=y +# CONFIG_POWER_SUPPLY_DEBUG is not set +CONFIG_PDA_POWER=m +CONFIG_BATTERY_DS2760=m +CONFIG_BATTERY_DS2782=m +CONFIG_BATTERY_BQ27x00=m +CONFIG_BATTERY_MAX17040=m +CONFIG_HWMON=m +CONFIG_HWMON_VID=m +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Native drivers +# +CONFIG_SENSORS_ABITUGURU=m +CONFIG_SENSORS_ABITUGURU3=m +CONFIG_SENSORS_AD7414=m +CONFIG_SENSORS_AD7418=m +CONFIG_SENSORS_ADCXX=m +CONFIG_SENSORS_ADM1021=m +CONFIG_SENSORS_ADM1025=m +CONFIG_SENSORS_ADM1026=m +CONFIG_SENSORS_ADM1029=m +CONFIG_SENSORS_ADM1031=m +CONFIG_SENSORS_ADM9240=m +CONFIG_SENSORS_ADT7462=m +CONFIG_SENSORS_ADT7470=m +CONFIG_SENSORS_ADT7473=m +CONFIG_SENSORS_ADT7475=m +CONFIG_SENSORS_K8TEMP=m +CONFIG_SENSORS_ASB100=m +CONFIG_SENSORS_ATXP1=m +CONFIG_SENSORS_DS1621=m +CONFIG_SENSORS_I5K_AMB=m +CONFIG_SENSORS_F71805F=m +CONFIG_SENSORS_F71882FG=m +CONFIG_SENSORS_F75375S=m +CONFIG_SENSORS_FSCHMD=m +CONFIG_SENSORS_G760A=m +CONFIG_SENSORS_GL518SM=m +CONFIG_SENSORS_GL520SM=m +CONFIG_SENSORS_CORETEMP=m +CONFIG_SENSORS_IBMAEM=m +CONFIG_SENSORS_IBMPEX=m +CONFIG_SENSORS_IT87=m +CONFIG_SENSORS_LM63=m +CONFIG_SENSORS_LM70=m +CONFIG_SENSORS_LM75=m +CONFIG_SENSORS_LM77=m +CONFIG_SENSORS_LM78=m +CONFIG_SENSORS_LM80=m +CONFIG_SENSORS_LM83=m +CONFIG_SENSORS_LM85=m +CONFIG_SENSORS_LM87=m +CONFIG_SENSORS_LM90=m +CONFIG_SENSORS_LM92=m +CONFIG_SENSORS_LM93=m +CONFIG_SENSORS_LTC4215=m +CONFIG_SENSORS_LTC4245=m +CONFIG_SENSORS_LM95241=m +CONFIG_SENSORS_MAX1111=m +CONFIG_SENSORS_MAX1619=m +CONFIG_SENSORS_MAX6650=m +CONFIG_SENSORS_PC87360=m +CONFIG_SENSORS_PC87427=m +CONFIG_SENSORS_PCF8591=m +CONFIG_SENSORS_SHT15=m +CONFIG_SENSORS_SIS5595=m +CONFIG_SENSORS_DME1737=m +CONFIG_SENSORS_SMSC47M1=m +CONFIG_SENSORS_SMSC47M192=m +CONFIG_SENSORS_SMSC47B397=m +CONFIG_SENSORS_ADS7828=m +CONFIG_SENSORS_THMC50=m +CONFIG_SENSORS_TMP401=m +CONFIG_SENSORS_TMP421=m +CONFIG_SENSORS_VIA686A=m +CONFIG_SENSORS_VT1211=m +CONFIG_SENSORS_VT8231=m +CONFIG_SENSORS_W83781D=m +CONFIG_SENSORS_W83791D=m +CONFIG_SENSORS_W83792D=m +CONFIG_SENSORS_W83793=m +CONFIG_SENSORS_W83L785TS=m +CONFIG_SENSORS_W83L786NG=m +CONFIG_SENSORS_W83627HF=m +CONFIG_SENSORS_W83627EHF=m +CONFIG_SENSORS_HDAPS=m +CONFIG_SENSORS_APPLESMC=m + +# +# ACPI drivers +# +CONFIG_SENSORS_ATK0110=m +CONFIG_SENSORS_LIS3LV02D=m +CONFIG_THERMAL=m +CONFIG_THERMAL_HWMON=y +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +CONFIG_SOFT_WATCHDOG=m +CONFIG_ACQUIRE_WDT=m +CONFIG_ADVANTECH_WDT=m +CONFIG_ALIM1535_WDT=m +CONFIG_ALIM7101_WDT=m +CONFIG_SC520_WDT=m +CONFIG_SBC_FITPC2_WATCHDOG=m +CONFIG_EUROTECH_WDT=m +CONFIG_IB700_WDT=m +CONFIG_IBMASR=m +CONFIG_WAFER_WDT=m +CONFIG_I6300ESB_WDT=m +CONFIG_ITCO_WDT=m +CONFIG_ITCO_VENDOR_SUPPORT=y +CONFIG_IT8712F_WDT=m +CONFIG_IT87_WDT=m +CONFIG_HP_WATCHDOG=m +CONFIG_SC1200_WDT=m +CONFIG_PC87413_WDT=m +CONFIG_60XX_WDT=m +CONFIG_SBC8360_WDT=m +CONFIG_CPU5_WDT=m +CONFIG_SMSC_SCH311X_WDT=m +CONFIG_SMSC37B787_WDT=m +CONFIG_W83627HF_WDT=m +CONFIG_W83697HF_WDT=m +CONFIG_W83697UG_WDT=m +CONFIG_W83877F_WDT=m +CONFIG_W83977F_WDT=m +CONFIG_MACHZ_WDT=m +CONFIG_SBC_EPX_C3_WATCHDOG=m + +# +# PCI-based Watchdog Cards +# +CONFIG_PCIPCWATCHDOG=m +CONFIG_WDTPCI=m + +# +# USB-based Watchdog Cards +# +CONFIG_USBPCWATCHDOG=m +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +CONFIG_SSB=m +CONFIG_SSB_SPROM=y +CONFIG_SSB_BLOCKIO=y +CONFIG_SSB_PCIHOST_POSSIBLE=y +CONFIG_SSB_PCIHOST=y +CONFIG_SSB_B43_PCI_BRIDGE=y +CONFIG_SSB_PCMCIAHOST_POSSIBLE=y +CONFIG_SSB_PCMCIAHOST=y +CONFIG_SSB_SDIOHOST_POSSIBLE=y +CONFIG_SSB_SDIOHOST=y +# CONFIG_SSB_DEBUG is not set +CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y +CONFIG_SSB_DRIVER_PCICORE=y + +# +# Multifunction device drivers +# +CONFIG_MFD_CORE=m +CONFIG_MFD_SM501=m +CONFIG_MFD_SM501_GPIO=y +CONFIG_HTC_PASIC3=m +CONFIG_UCB1400_CORE=m +CONFIG_TPS65010=m +# CONFIG_MFD_TMIO is not set +CONFIG_MFD_WM8400=m +# CONFIG_MFD_WM831X is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_PCF50633 is not set +CONFIG_MFD_MC13783=m +CONFIG_AB3100_CORE=m +CONFIG_AB3100_OTP=m +CONFIG_EZX_PCAP=y +CONFIG_REGULATOR=y +# CONFIG_REGULATOR_DEBUG is not set +# CONFIG_REGULATOR_FIXED_VOLTAGE is not set +CONFIG_REGULATOR_VIRTUAL_CONSUMER=m +CONFIG_REGULATOR_USERSPACE_CONSUMER=m +CONFIG_REGULATOR_BQ24022=m +CONFIG_REGULATOR_MAX1586=m +CONFIG_REGULATOR_WM8400=m +CONFIG_REGULATOR_LP3971=m +CONFIG_REGULATOR_PCAP=m +CONFIG_REGULATOR_MC13783=m +CONFIG_REGULATOR_AB3100=m +CONFIG_REGULATOR_TPS65023=m +CONFIG_REGULATOR_TPS6507X=m +CONFIG_MEDIA_SUPPORT=m + +# +# Multimedia core support +# +CONFIG_VIDEO_DEV=m +CONFIG_VIDEO_V4L2_COMMON=m +CONFIG_VIDEO_ALLOW_V4L1=y +CONFIG_VIDEO_V4L1_COMPAT=y +CONFIG_DVB_CORE=m +CONFIG_VIDEO_MEDIA=m + +# +# Multimedia drivers +# +CONFIG_VIDEO_SAA7146=m +CONFIG_VIDEO_SAA7146_VV=m +CONFIG_MEDIA_ATTACH=y +CONFIG_MEDIA_TUNER=m +# CONFIG_MEDIA_TUNER_CUSTOMISE is not set +CONFIG_MEDIA_TUNER_SIMPLE=m +CONFIG_MEDIA_TUNER_TDA8290=m +CONFIG_MEDIA_TUNER_TDA827X=m +CONFIG_MEDIA_TUNER_TDA18271=m +CONFIG_MEDIA_TUNER_TDA9887=m +CONFIG_MEDIA_TUNER_TEA5761=m +CONFIG_MEDIA_TUNER_TEA5767=m +CONFIG_MEDIA_TUNER_MT20XX=m +CONFIG_MEDIA_TUNER_MT2060=m +CONFIG_MEDIA_TUNER_MT2266=m +CONFIG_MEDIA_TUNER_MT2131=m +CONFIG_MEDIA_TUNER_QT1010=m +CONFIG_MEDIA_TUNER_XC2028=m +CONFIG_MEDIA_TUNER_XC5000=m +CONFIG_MEDIA_TUNER_MXL5005S=m +CONFIG_MEDIA_TUNER_MXL5007T=m +CONFIG_MEDIA_TUNER_MC44S803=m +CONFIG_VIDEO_V4L2=m +CONFIG_VIDEO_V4L1=m +CONFIG_VIDEOBUF_GEN=m +CONFIG_VIDEOBUF_DMA_SG=m +CONFIG_VIDEOBUF_VMALLOC=m +CONFIG_VIDEOBUF_DVB=m +CONFIG_VIDEO_BTCX=m +CONFIG_VIDEO_IR=m +CONFIG_VIDEO_TVEEPROM=m +CONFIG_VIDEO_TUNER=m +CONFIG_VIDEO_CAPTURE_DRIVERS=y +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set +CONFIG_VIDEO_HELPER_CHIPS_AUTO=y +CONFIG_VIDEO_IR_I2C=m +CONFIG_VIDEO_TVAUDIO=m +CONFIG_VIDEO_TDA7432=m +CONFIG_VIDEO_TDA9840=m +CONFIG_VIDEO_TEA6415C=m +CONFIG_VIDEO_TEA6420=m +CONFIG_VIDEO_MSP3400=m +CONFIG_VIDEO_CS5345=m +CONFIG_VIDEO_CS53L32A=m +CONFIG_VIDEO_M52790=m +CONFIG_VIDEO_WM8775=m +CONFIG_VIDEO_WM8739=m +CONFIG_VIDEO_VP27SMPX=m +CONFIG_VIDEO_SAA6588=m +CONFIG_VIDEO_BT819=m +CONFIG_VIDEO_BT856=m +CONFIG_VIDEO_BT866=m +CONFIG_VIDEO_KS0127=m +CONFIG_VIDEO_OV7670=m +CONFIG_VIDEO_MT9V011=m +CONFIG_VIDEO_SAA7110=m +CONFIG_VIDEO_SAA711X=m +CONFIG_VIDEO_SAA717X=m +CONFIG_VIDEO_TVP5150=m +CONFIG_VIDEO_VPX3220=m +CONFIG_VIDEO_CX25840=m +CONFIG_VIDEO_CX2341X=m +CONFIG_VIDEO_SAA7127=m +CONFIG_VIDEO_SAA7185=m +CONFIG_VIDEO_ADV7170=m +CONFIG_VIDEO_ADV7175=m +CONFIG_VIDEO_UPD64031A=m +CONFIG_VIDEO_UPD64083=m +CONFIG_VIDEO_VIVI=m +CONFIG_VIDEO_BT848=m +CONFIG_VIDEO_BT848_DVB=y +CONFIG_VIDEO_BWQCAM=m +CONFIG_VIDEO_CQCAM=m +CONFIG_VIDEO_W9966=m +CONFIG_VIDEO_CPIA=m +CONFIG_VIDEO_CPIA_PP=m +CONFIG_VIDEO_CPIA_USB=m +CONFIG_VIDEO_CPIA2=m +CONFIG_VIDEO_SAA5246A=m +CONFIG_VIDEO_SAA5249=m +CONFIG_VIDEO_STRADIS=m +CONFIG_VIDEO_ZORAN=m +CONFIG_VIDEO_ZORAN_DC30=m +CONFIG_VIDEO_ZORAN_ZR36060=m +CONFIG_VIDEO_ZORAN_BUZ=m +CONFIG_VIDEO_ZORAN_DC10=m +CONFIG_VIDEO_ZORAN_LML33=m +CONFIG_VIDEO_ZORAN_LML33R10=m +CONFIG_VIDEO_ZORAN_AVS6EYES=m +CONFIG_VIDEO_MEYE=m +CONFIG_VIDEO_SAA7134=m +CONFIG_VIDEO_SAA7134_ALSA=m +CONFIG_VIDEO_SAA7134_DVB=m +CONFIG_VIDEO_MXB=m +CONFIG_VIDEO_HEXIUM_ORION=m +CONFIG_VIDEO_HEXIUM_GEMINI=m +CONFIG_VIDEO_CX88=m +CONFIG_VIDEO_CX88_ALSA=m +CONFIG_VIDEO_CX88_BLACKBIRD=m +CONFIG_VIDEO_CX88_DVB=m +CONFIG_VIDEO_CX88_MPEG=m +CONFIG_VIDEO_CX88_VP3054=m +CONFIG_VIDEO_CX23885=m +CONFIG_VIDEO_AU0828=m +CONFIG_VIDEO_IVTV=m +CONFIG_VIDEO_FB_IVTV=m +CONFIG_VIDEO_CX18=m +CONFIG_VIDEO_SAA7164=m +CONFIG_VIDEO_CAFE_CCIC=m +CONFIG_SOC_CAMERA=m +CONFIG_SOC_CAMERA_MT9M001=m +CONFIG_SOC_CAMERA_MT9M111=m +CONFIG_SOC_CAMERA_MT9T031=m +CONFIG_SOC_CAMERA_MT9V022=m +CONFIG_SOC_CAMERA_TW9910=m +CONFIG_SOC_CAMERA_PLATFORM=m +CONFIG_SOC_CAMERA_OV772X=m +CONFIG_V4L_USB_DRIVERS=y +CONFIG_USB_VIDEO_CLASS=m +CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y +CONFIG_USB_GSPCA=m +CONFIG_USB_M5602=m +CONFIG_USB_STV06XX=m +CONFIG_USB_GL860=m +CONFIG_USB_GSPCA_CONEX=m +CONFIG_USB_GSPCA_ETOMS=m +CONFIG_USB_GSPCA_FINEPIX=m +CONFIG_USB_GSPCA_JEILINJ=m +CONFIG_USB_GSPCA_MARS=m +CONFIG_USB_GSPCA_MR97310A=m +CONFIG_USB_GSPCA_OV519=m +CONFIG_USB_GSPCA_OV534=m +CONFIG_USB_GSPCA_PAC207=m +CONFIG_USB_GSPCA_PAC7311=m +CONFIG_USB_GSPCA_SN9C20X=m +CONFIG_USB_GSPCA_SN9C20X_EVDEV=y +CONFIG_USB_GSPCA_SONIXB=m +CONFIG_USB_GSPCA_SONIXJ=m +CONFIG_USB_GSPCA_SPCA500=m +CONFIG_USB_GSPCA_SPCA501=m +CONFIG_USB_GSPCA_SPCA505=m +CONFIG_USB_GSPCA_SPCA506=m +CONFIG_USB_GSPCA_SPCA508=m +CONFIG_USB_GSPCA_SPCA561=m +CONFIG_USB_GSPCA_SQ905=m +CONFIG_USB_GSPCA_SQ905C=m +CONFIG_USB_GSPCA_STK014=m +CONFIG_USB_GSPCA_SUNPLUS=m +CONFIG_USB_GSPCA_T613=m +CONFIG_USB_GSPCA_TV8532=m +CONFIG_USB_GSPCA_VC032X=m +CONFIG_USB_GSPCA_ZC3XX=m +CONFIG_VIDEO_PVRUSB2=m +CONFIG_VIDEO_PVRUSB2_SYSFS=y +CONFIG_VIDEO_PVRUSB2_DVB=y +# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set +CONFIG_VIDEO_HDPVR=m +CONFIG_VIDEO_EM28XX=m +CONFIG_VIDEO_EM28XX_ALSA=m +CONFIG_VIDEO_EM28XX_DVB=m +CONFIG_VIDEO_CX231XX=m +CONFIG_VIDEO_CX231XX_ALSA=m +CONFIG_VIDEO_CX231XX_DVB=m +CONFIG_VIDEO_USBVISION=m +CONFIG_VIDEO_USBVIDEO=m +CONFIG_USB_VICAM=m +CONFIG_USB_IBMCAM=m +CONFIG_USB_KONICAWC=m +CONFIG_USB_QUICKCAM_MESSENGER=m +CONFIG_USB_ET61X251=m +CONFIG_VIDEO_OVCAMCHIP=m +CONFIG_USB_W9968CF=m +CONFIG_USB_OV511=m +CONFIG_USB_SE401=m +CONFIG_USB_SN9C102=m +CONFIG_USB_STV680=m +CONFIG_USB_ZC0301=m +CONFIG_USB_PWC=m +# CONFIG_USB_PWC_DEBUG is not set +CONFIG_USB_PWC_INPUT_EVDEV=y +CONFIG_USB_ZR364XX=m +CONFIG_USB_STKWEBCAM=m +CONFIG_USB_S2255=m +CONFIG_RADIO_ADAPTERS=y +CONFIG_RADIO_GEMTEK_PCI=m +CONFIG_RADIO_MAXIRADIO=m +CONFIG_RADIO_MAESTRO=m +CONFIG_I2C_SI4713=m +CONFIG_RADIO_SI4713=m +CONFIG_USB_DSBR=m +CONFIG_RADIO_SI470X=y +CONFIG_USB_SI470X=m +CONFIG_I2C_SI470X=m +CONFIG_USB_MR800=m +CONFIG_RADIO_TEA5764=m +CONFIG_DVB_MAX_ADAPTERS=8 +CONFIG_DVB_DYNAMIC_MINORS=y +CONFIG_DVB_CAPTURE_DRIVERS=y + +# +# Supported SAA7146 based PCI Adapters +# +CONFIG_TTPCI_EEPROM=m +CONFIG_DVB_AV7110=m +CONFIG_DVB_AV7110_OSD=y +CONFIG_DVB_BUDGET_CORE=m +CONFIG_DVB_BUDGET=m +CONFIG_DVB_BUDGET_CI=m +CONFIG_DVB_BUDGET_AV=m +CONFIG_DVB_BUDGET_PATCH=m + +# +# Supported USB Adapters +# +CONFIG_DVB_USB=m +# CONFIG_DVB_USB_DEBUG is not set +CONFIG_DVB_USB_A800=m +CONFIG_DVB_USB_DIBUSB_MB=m +# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set +CONFIG_DVB_USB_DIBUSB_MC=m +CONFIG_DVB_USB_DIB0700=m +CONFIG_DVB_USB_UMT_010=m +CONFIG_DVB_USB_CXUSB=m +CONFIG_DVB_USB_M920X=m +CONFIG_DVB_USB_GL861=m +CONFIG_DVB_USB_AU6610=m +CONFIG_DVB_USB_DIGITV=m +CONFIG_DVB_USB_VP7045=m +CONFIG_DVB_USB_VP702X=m +CONFIG_DVB_USB_GP8PSK=m +CONFIG_DVB_USB_NOVA_T_USB2=m +CONFIG_DVB_USB_TTUSB2=m +CONFIG_DVB_USB_DTT200U=m +CONFIG_DVB_USB_OPERA1=m +CONFIG_DVB_USB_AF9005=m +CONFIG_DVB_USB_AF9005_REMOTE=m +CONFIG_DVB_USB_DW2102=m +CONFIG_DVB_USB_CINERGY_T2=m +CONFIG_DVB_USB_ANYSEE=m +CONFIG_DVB_USB_DTV5100=m +CONFIG_DVB_USB_AF9015=m +CONFIG_DVB_USB_CE6230=m +CONFIG_DVB_USB_FRIIO=m +CONFIG_DVB_TTUSB_BUDGET=m +CONFIG_DVB_TTUSB_DEC=m +CONFIG_SMS_SIANO_MDTV=m + +# +# Siano module components +# +CONFIG_SMS_USB_DRV=m +CONFIG_SMS_SDIO_DRV=m + +# +# Supported FlexCopII (B2C2) Adapters +# +CONFIG_DVB_B2C2_FLEXCOP=m +CONFIG_DVB_B2C2_FLEXCOP_PCI=m +CONFIG_DVB_B2C2_FLEXCOP_USB=m +# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set + +# +# Supported BT878 Adapters +# +CONFIG_DVB_BT8XX=m + +# +# Supported Pluto2 Adapters +# +CONFIG_DVB_PLUTO2=m + +# +# Supported SDMC DM1105 Adapters +# +CONFIG_DVB_DM1105=m + +# +# Supported FireWire (IEEE 1394) Adapters +# +CONFIG_DVB_FIREDTV=m +CONFIG_DVB_FIREDTV_IEEE1394=y +CONFIG_DVB_FIREDTV_INPUT=y + +# +# Supported Earthsoft PT1 Adapters +# +CONFIG_DVB_PT1=m + +# +# Supported DVB Frontends +# +CONFIG_DVB_FE_CUSTOMISE=y + +# +# Customise DVB Frontends +# + +# +# Multistandard (satellite) frontends +# +CONFIG_DVB_STB0899=m +CONFIG_DVB_STB6100=m +# CONFIG_DVB_STV090x is not set +# CONFIG_DVB_STV6110x is not set + +# +# DVB-S (satellite) frontends +# +CONFIG_DVB_CX24110=m +CONFIG_DVB_CX24123=m +CONFIG_DVB_MT312=m +CONFIG_DVB_ZL10036=m +CONFIG_DVB_ZL10039=m +CONFIG_DVB_S5H1420=m +CONFIG_DVB_STV0288=m +CONFIG_DVB_STB6000=m +CONFIG_DVB_STV0299=m +CONFIG_DVB_STV6110=m +CONFIG_DVB_STV0900=m +CONFIG_DVB_TDA8083=m +CONFIG_DVB_TDA10086=m +CONFIG_DVB_TDA8261=m +CONFIG_DVB_VES1X93=m +CONFIG_DVB_TUNER_ITD1000=m +CONFIG_DVB_TUNER_CX24113=m +CONFIG_DVB_TDA826X=m +CONFIG_DVB_TUA6100=m +CONFIG_DVB_CX24116=m +CONFIG_DVB_SI21XX=m + +# +# DVB-T (terrestrial) frontends +# +CONFIG_DVB_SP8870=m +CONFIG_DVB_SP887X=m +CONFIG_DVB_CX22700=m +CONFIG_DVB_CX22702=m +# CONFIG_DVB_DRX397XD is not set +CONFIG_DVB_L64781=m +CONFIG_DVB_TDA1004X=m +CONFIG_DVB_NXT6000=m +CONFIG_DVB_MT352=m +CONFIG_DVB_ZL10353=m +CONFIG_DVB_DIB3000MB=m +CONFIG_DVB_DIB3000MC=m +CONFIG_DVB_DIB7000M=m +CONFIG_DVB_DIB7000P=m +CONFIG_DVB_TDA10048=m +CONFIG_DVB_AF9013=m + +# +# DVB-C (cable) frontends +# +CONFIG_DVB_VES1820=m +CONFIG_DVB_TDA10021=m +CONFIG_DVB_TDA10023=m +CONFIG_DVB_STV0297=m + +# +# ATSC (North American/Korean Terrestrial/Cable DTV) frontends +# +CONFIG_DVB_NXT200X=m +CONFIG_DVB_OR51211=m +CONFIG_DVB_OR51132=m +CONFIG_DVB_BCM3510=m +CONFIG_DVB_LGDT330X=m +# CONFIG_DVB_LGDT3304 is not set +CONFIG_DVB_LGDT3305=m +CONFIG_DVB_S5H1409=m +CONFIG_DVB_AU8522=m +CONFIG_DVB_S5H1411=m + +# +# ISDB-T (terrestrial) frontends +# +# CONFIG_DVB_S921 is not set +CONFIG_DVB_DIB8000=m + +# +# Digital terrestrial only tuners/PLL +# +CONFIG_DVB_PLL=m +CONFIG_DVB_TUNER_DIB0070=m + +# +# SEC control devices for DVB-S +# +CONFIG_DVB_LNBP21=m +CONFIG_DVB_ISL6405=m +CONFIG_DVB_ISL6421=m +# CONFIG_DVB_ISL6423 is not set +CONFIG_DVB_LGS8GL5=m +CONFIG_DVB_LGS8GXX=m + +# +# Tools to develop new frontends +# +# CONFIG_DVB_DUMMY_FE is not set +CONFIG_DAB=y +CONFIG_USB_DABUSB=m + +# +# Graphics support +# +CONFIG_AGP=m +CONFIG_AGP_AMD64=m +CONFIG_AGP_INTEL=m +CONFIG_AGP_SIS=m +CONFIG_AGP_VIA=m +CONFIG_VGA_ARB=y +CONFIG_DRM=m +CONFIG_DRM_KMS_HELPER=m +CONFIG_DRM_TTM=m +CONFIG_DRM_TDFX=m +CONFIG_DRM_R128=m +CONFIG_DRM_RADEON=m +CONFIG_DRM_I810=m +CONFIG_DRM_I830=m +CONFIG_DRM_I915=m +CONFIG_DRM_I915_KMS=y +CONFIG_DRM_MGA=m +CONFIG_DRM_SIS=m +CONFIG_DRM_VIA=m +CONFIG_DRM_SAVAGE=m +CONFIG_VGASTATE=m +CONFIG_VIDEO_OUTPUT_CONTROL=m +CONFIG_FB=y +CONFIG_FIRMWARE_EDID=y +CONFIG_FB_DDC=m +CONFIG_FB_BOOT_VESA_SUPPORT=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +CONFIG_FB_SYS_FILLRECT=m +CONFIG_FB_SYS_COPYAREA=m +CONFIG_FB_SYS_IMAGEBLIT=m +# CONFIG_FB_FOREIGN_ENDIAN is not set +CONFIG_FB_SYS_FOPS=m +CONFIG_FB_DEFERRED_IO=y +CONFIG_FB_HECUBA=m +CONFIG_FB_SVGALIB=m +# CONFIG_FB_MACMODES is not set +CONFIG_FB_BACKLIGHT=y +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_TILEBLITTING=y + +# +# Frame buffer hardware drivers +# +CONFIG_FB_CIRRUS=m +CONFIG_FB_PM2=m +CONFIG_FB_PM2_FIFO_DISCONNECT=y +CONFIG_FB_CYBER2000=m +CONFIG_FB_ARC=m +# CONFIG_FB_ASILIANT is not set +# CONFIG_FB_IMSTT is not set +CONFIG_FB_VGA16=m +CONFIG_FB_UVESA=m +CONFIG_FB_VESA=y +CONFIG_FB_N411=m +CONFIG_FB_HGA=m +CONFIG_FB_HGA_ACCEL=y +CONFIG_FB_S1D13XXX=m +CONFIG_FB_NVIDIA=m +CONFIG_FB_NVIDIA_I2C=y +# CONFIG_FB_NVIDIA_DEBUG is not set +CONFIG_FB_NVIDIA_BACKLIGHT=y +CONFIG_FB_RIVA=m +CONFIG_FB_RIVA_I2C=y +# CONFIG_FB_RIVA_DEBUG is not set +CONFIG_FB_RIVA_BACKLIGHT=y +CONFIG_FB_LE80578=m +CONFIG_FB_CARILLO_RANCH=m +CONFIG_FB_MATROX=m +CONFIG_FB_MATROX_MILLENIUM=y +CONFIG_FB_MATROX_MYSTIQUE=y +CONFIG_FB_MATROX_G=y +CONFIG_FB_MATROX_I2C=m +CONFIG_FB_MATROX_MAVEN=m +CONFIG_FB_RADEON=m +CONFIG_FB_RADEON_I2C=y +CONFIG_FB_RADEON_BACKLIGHT=y +# CONFIG_FB_RADEON_DEBUG is not set +CONFIG_FB_ATY128=m +CONFIG_FB_ATY128_BACKLIGHT=y +CONFIG_FB_ATY=m +CONFIG_FB_ATY_CT=y +CONFIG_FB_ATY_GENERIC_LCD=y +CONFIG_FB_ATY_GX=y +CONFIG_FB_ATY_BACKLIGHT=y +CONFIG_FB_S3=m +CONFIG_FB_SAVAGE=m +CONFIG_FB_SAVAGE_I2C=y +CONFIG_FB_SAVAGE_ACCEL=y +CONFIG_FB_SIS=m +CONFIG_FB_SIS_300=y +CONFIG_FB_SIS_315=y +CONFIG_FB_VIA=m +CONFIG_FB_NEOMAGIC=m +CONFIG_FB_KYRO=m +CONFIG_FB_3DFX=m +CONFIG_FB_3DFX_ACCEL=y +CONFIG_FB_3DFX_I2C=y +CONFIG_FB_VOODOO1=m +CONFIG_FB_VT8623=m +CONFIG_FB_TRIDENT=m +CONFIG_FB_ARK=m +CONFIG_FB_PM3=m +CONFIG_FB_CARMINE=m +CONFIG_FB_CARMINE_DRAM_EVAL=y +# CONFIG_CARMINE_DRAM_CUSTOM is not set +CONFIG_FB_GEODE=y +CONFIG_FB_GEODE_LX=m +CONFIG_FB_GEODE_GX=m +CONFIG_FB_GEODE_GX1=m +CONFIG_FB_TMIO=m +CONFIG_FB_TMIO_ACCELL=y +CONFIG_FB_SM501=m +CONFIG_FB_VIRTUAL=m +CONFIG_FB_METRONOME=m +CONFIG_FB_MB862XX=m +CONFIG_FB_MB862XX_PCI_GDC=y +CONFIG_FB_BROADSHEET=m +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_LCD_CLASS_DEVICE=m +CONFIG_LCD_LMS283GF05=m +CONFIG_LCD_LTV350QV=m +CONFIG_LCD_ILI9320=m +CONFIG_LCD_TDO24M=m +CONFIG_LCD_VGG2432A4=m +CONFIG_LCD_PLATFORM=m +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_BACKLIGHT_GENERIC=m +CONFIG_BACKLIGHT_PROGEAR=m +CONFIG_BACKLIGHT_CARILLO_RANCH=m +CONFIG_BACKLIGHT_MBP_NVIDIA=m +CONFIG_BACKLIGHT_SAHARA=m + +# +# Display device support +# +CONFIG_DISPLAY_SUPPORT=m + +# +# Display hardware drivers +# + +# +# Console display driver support +# +CONFIG_VGA_CONSOLE=y +CONFIG_VGACON_SOFT_SCROLLBACK=y +CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64 +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +# CONFIG_LOGO is not set +CONFIG_SOUND=m +CONFIG_SOUND_OSS_CORE=y +# CONFIG_SOUND_OSS_CORE_PRECLAIM is not set +CONFIG_SND=m +CONFIG_SND_TIMER=m +CONFIG_SND_PCM=m +CONFIG_SND_HWDEP=m +CONFIG_SND_RAWMIDI=m +CONFIG_SND_JACK=y +CONFIG_SND_SEQUENCER=m +CONFIG_SND_SEQ_DUMMY=m +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=m +CONFIG_SND_PCM_OSS=m +CONFIG_SND_PCM_OSS_PLUGINS=y +CONFIG_SND_SEQUENCER_OSS=y +CONFIG_SND_DYNAMIC_MINORS=y +CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_VERBOSE_PROCFS=y +CONFIG_SND_VERBOSE_PRINTK=y +CONFIG_SND_DEBUG=y +# CONFIG_SND_DEBUG_VERBOSE is not set +CONFIG_SND_PCM_XRUN_DEBUG=y +CONFIG_SND_VMASTER=y +CONFIG_SND_DMA_SGBUF=y +CONFIG_SND_RAWMIDI_SEQ=m +CONFIG_SND_OPL3_LIB_SEQ=m +# CONFIG_SND_OPL4_LIB_SEQ is not set +# CONFIG_SND_SBAWE_SEQ is not set +CONFIG_SND_EMU10K1_SEQ=m +CONFIG_SND_MPU401_UART=m +CONFIG_SND_OPL3_LIB=m +CONFIG_SND_VX_LIB=m +CONFIG_SND_AC97_CODEC=m +CONFIG_SND_DRIVERS=y +CONFIG_SND_DUMMY=m +CONFIG_SND_VIRMIDI=m +CONFIG_SND_MTPAV=m +CONFIG_SND_MTS64=m +CONFIG_SND_SERIAL_U16550=m +CONFIG_SND_MPU401=m +CONFIG_SND_PORTMAN2X4=m +CONFIG_SND_AC97_POWER_SAVE=y +CONFIG_SND_AC97_POWER_SAVE_DEFAULT=0 +CONFIG_SND_SB_COMMON=m +CONFIG_SND_SB16_DSP=m +CONFIG_SND_PCI=y +CONFIG_SND_AD1889=m +CONFIG_SND_ALS300=m +CONFIG_SND_ALS4000=m +CONFIG_SND_ALI5451=m +CONFIG_SND_ATIIXP=m +CONFIG_SND_ATIIXP_MODEM=m +CONFIG_SND_AU8810=m +CONFIG_SND_AU8820=m +CONFIG_SND_AU8830=m +CONFIG_SND_AW2=m +CONFIG_SND_AZT3328=m +CONFIG_SND_BT87X=m +# CONFIG_SND_BT87X_OVERCLOCK is not set +CONFIG_SND_CA0106=m +CONFIG_SND_CMIPCI=m +CONFIG_SND_OXYGEN_LIB=m +CONFIG_SND_OXYGEN=m +CONFIG_SND_CS4281=m +CONFIG_SND_CS46XX=m +CONFIG_SND_CS46XX_NEW_DSP=y +CONFIG_SND_CS5530=m +CONFIG_SND_CS5535AUDIO=m +CONFIG_SND_CTXFI=m +CONFIG_SND_DARLA20=m +CONFIG_SND_GINA20=m +CONFIG_SND_LAYLA20=m +CONFIG_SND_DARLA24=m +CONFIG_SND_GINA24=m +CONFIG_SND_LAYLA24=m +CONFIG_SND_MONA=m +CONFIG_SND_MIA=m +CONFIG_SND_ECHO3G=m +CONFIG_SND_INDIGO=m +CONFIG_SND_INDIGOIO=m +CONFIG_SND_INDIGODJ=m +CONFIG_SND_INDIGOIOX=m +CONFIG_SND_INDIGODJX=m +CONFIG_SND_EMU10K1=m +CONFIG_SND_EMU10K1X=m +CONFIG_SND_ENS1370=m +CONFIG_SND_ENS1371=m +CONFIG_SND_ES1938=m +CONFIG_SND_ES1968=m +CONFIG_SND_FM801=m +CONFIG_SND_FM801_TEA575X_BOOL=y +CONFIG_SND_FM801_TEA575X=m +CONFIG_SND_HDA_INTEL=m +CONFIG_SND_HDA_HWDEP=y +CONFIG_SND_HDA_RECONFIG=y +CONFIG_SND_HDA_INPUT_BEEP=y +CONFIG_SND_HDA_INPUT_JACK=y +CONFIG_SND_HDA_PATCH_LOADER=y +CONFIG_SND_HDA_CODEC_REALTEK=y +CONFIG_SND_HDA_CODEC_ANALOG=y +CONFIG_SND_HDA_CODEC_SIGMATEL=y +CONFIG_SND_HDA_CODEC_VIA=y +CONFIG_SND_HDA_CODEC_ATIHDMI=y +CONFIG_SND_HDA_CODEC_NVHDMI=y +CONFIG_SND_HDA_CODEC_INTELHDMI=y +CONFIG_SND_HDA_ELD=y +CONFIG_SND_HDA_CODEC_CIRRUS=y +CONFIG_SND_HDA_CODEC_CONEXANT=y +CONFIG_SND_HDA_CODEC_CA0110=y +CONFIG_SND_HDA_CODEC_CMEDIA=y +CONFIG_SND_HDA_CODEC_SI3054=y +CONFIG_SND_HDA_GENERIC=y +CONFIG_SND_HDA_POWER_SAVE=y +CONFIG_SND_HDA_POWER_SAVE_DEFAULT=0 +CONFIG_SND_HDSP=m +CONFIG_SND_HDSPM=m +CONFIG_SND_HIFIER=m +CONFIG_SND_ICE1712=m +CONFIG_SND_ICE1724=m +CONFIG_SND_INTEL8X0=m +CONFIG_SND_INTEL8X0M=m +CONFIG_SND_KORG1212=m +CONFIG_SND_LX6464ES=m +CONFIG_SND_MAESTRO3=m +CONFIG_SND_MIXART=m +CONFIG_SND_NM256=m +CONFIG_SND_PCXHR=m +CONFIG_SND_RIPTIDE=m +CONFIG_SND_RME32=m +CONFIG_SND_RME96=m +CONFIG_SND_RME9652=m +CONFIG_SND_SONICVIBES=m +CONFIG_SND_TRIDENT=m +CONFIG_SND_VIA82XX=m +CONFIG_SND_VIA82XX_MODEM=m +CONFIG_SND_VIRTUOSO=m +CONFIG_SND_VX222=m +CONFIG_SND_YMFPCI=m +CONFIG_SND_SPI=y +CONFIG_SND_USB=y +CONFIG_SND_USB_AUDIO=m +CONFIG_SND_USB_USX2Y=m +CONFIG_SND_USB_CAIAQ=m +CONFIG_SND_USB_CAIAQ_INPUT=y +CONFIG_SND_USB_US122L=m +CONFIG_SND_PCMCIA=y +CONFIG_SND_VXPOCKET=m +CONFIG_SND_PDAUDIOCF=m +# CONFIG_SND_SOC is not set +CONFIG_SOUND_PRIME=m +CONFIG_SOUND_OSS=m +CONFIG_SOUND_TRACEINIT=y +CONFIG_SOUND_DMAP=y +CONFIG_SOUND_SSCAPE=m +CONFIG_SOUND_VMIDI=m +CONFIG_SOUND_TRIX=m +CONFIG_SOUND_MSS=m +CONFIG_SOUND_MPU401=m +CONFIG_SOUND_PAS=m +CONFIG_SOUND_PSS=m +CONFIG_PSS_MIXER=y +# CONFIG_PSS_HAVE_BOOT is not set +# CONFIG_SOUND_SB is not set +CONFIG_SOUND_YM3812=m +CONFIG_SOUND_UART6850=m +CONFIG_SOUND_AEDSP16=m +CONFIG_SC6600=y +CONFIG_SC6600_JOY=y +CONFIG_SC6600_CDROM=4 +CONFIG_SC6600_CDROMBASE=0 +CONFIG_AC97_BUS=m +CONFIG_HID_SUPPORT=y +CONFIG_HID=m +CONFIG_HIDRAW=y + +# +# USB Input Devices +# +CONFIG_USB_HID=m +CONFIG_HID_PID=y +CONFIG_USB_HIDDEV=y + +# +# Special HID drivers +# +CONFIG_HID_A4TECH=m +CONFIG_HID_APPLE=m +CONFIG_HID_BELKIN=m +CONFIG_HID_CHERRY=m +CONFIG_HID_CHICONY=m +CONFIG_HID_CYPRESS=m +CONFIG_HID_DRAGONRISE=m +CONFIG_DRAGONRISE_FF=y +CONFIG_HID_EZKEY=m +CONFIG_HID_KYE=m +CONFIG_HID_GYRATION=m +CONFIG_HID_TWINHAN=m +CONFIG_HID_KENSINGTON=m +CONFIG_HID_LOGITECH=m +CONFIG_LOGITECH_FF=y +CONFIG_LOGIRUMBLEPAD2_FF=y +CONFIG_HID_MICROSOFT=m +CONFIG_HID_MONTEREY=m +CONFIG_HID_NTRIG=m +CONFIG_HID_PANTHERLORD=m +CONFIG_PANTHERLORD_FF=y +CONFIG_HID_PETALYNX=m +CONFIG_HID_SAMSUNG=m +CONFIG_HID_SONY=m +CONFIG_HID_SUNPLUS=m +CONFIG_HID_GREENASIA=m +CONFIG_GREENASIA_FF=y +CONFIG_HID_SMARTJOYPLUS=m +CONFIG_SMARTJOYPLUS_FF=y +CONFIG_HID_TOPSEED=m +CONFIG_HID_THRUSTMASTER=m +CONFIG_THRUSTMASTER_FF=y +CONFIG_HID_WACOM=m +CONFIG_HID_ZEROPLUS=m +CONFIG_ZEROPLUS_FF=y +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB=m +# CONFIG_USB_DEBUG is not set +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_DEVICE_CLASS is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +CONFIG_USB_SUSPEND=y +# CONFIG_USB_OTG is not set +CONFIG_USB_MON=m +CONFIG_USB_WUSB=m +CONFIG_USB_WUSB_CBAF=m +# CONFIG_USB_WUSB_CBAF_DEBUG is not set + +# +# USB Host Controller Drivers +# +CONFIG_USB_C67X00_HCD=m +CONFIG_USB_XHCI_HCD=m +# CONFIG_USB_XHCI_HCD_DEBUGGING is not set +CONFIG_USB_EHCI_HCD=m +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +CONFIG_USB_OXU210HP_HCD=m +CONFIG_USB_ISP116X_HCD=m +CONFIG_USB_ISP1760_HCD=m +CONFIG_USB_ISP1362_HCD=m +CONFIG_USB_OHCI_HCD=m +# CONFIG_USB_OHCI_HCD_SSB is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +CONFIG_USB_UHCI_HCD=m +CONFIG_USB_U132_HCD=m +CONFIG_USB_SL811_HCD=m +CONFIG_USB_SL811_CS=m +CONFIG_USB_R8A66597_HCD=m +CONFIG_USB_WHCI_HCD=m +CONFIG_USB_HWA_HCD=m + +# +# Enable Host or Gadget support to see Inventra options +# + +# +# USB Device Class drivers +# +CONFIG_USB_ACM=m +CONFIG_USB_PRINTER=m +CONFIG_USB_WDM=m +CONFIG_USB_TMC=m + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may +# + +# +# also be needed; see USB_STORAGE Help for more info +# +CONFIG_USB_STORAGE=m +# CONFIG_USB_STORAGE_DEBUG is not set +CONFIG_USB_STORAGE_DATAFAB=m +CONFIG_USB_STORAGE_FREECOM=m +CONFIG_USB_STORAGE_ISD200=m +CONFIG_USB_STORAGE_USBAT=m +CONFIG_USB_STORAGE_SDDR09=m +CONFIG_USB_STORAGE_SDDR55=m +CONFIG_USB_STORAGE_JUMPSHOT=m +CONFIG_USB_STORAGE_ALAUDA=m +CONFIG_USB_STORAGE_ONETOUCH=m +CONFIG_USB_STORAGE_KARMA=m +CONFIG_USB_STORAGE_CYPRESS_ATACB=m +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Imaging devices +# +CONFIG_USB_MDC800=m +CONFIG_USB_MICROTEK=m + +# +# USB port drivers +# +CONFIG_USB_USS720=m +CONFIG_USB_SERIAL=m +CONFIG_USB_EZUSB=y +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_AIRCABLE=m +CONFIG_USB_SERIAL_ARK3116=m +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_CH341=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_CP210X=m +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_FUNSOFT=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_GARMIN=m +CONFIG_USB_SERIAL_IPW=m +CONFIG_USB_SERIAL_IUU=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +CONFIG_USB_SERIAL_KEYSPAN_MPR=y +CONFIG_USB_SERIAL_KEYSPAN_USA28=y +CONFIG_USB_SERIAL_KEYSPAN_USA28X=y +CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y +CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y +CONFIG_USB_SERIAL_KEYSPAN_USA19=y +CONFIG_USB_SERIAL_KEYSPAN_USA18X=y +CONFIG_USB_SERIAL_KEYSPAN_USA19W=y +CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y +CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y +CONFIG_USB_SERIAL_KEYSPAN_USA49W=y +CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_MOS7720=m +CONFIG_USB_SERIAL_MOS7840=m +CONFIG_USB_SERIAL_MOTOROLA=m +CONFIG_USB_SERIAL_NAVMAN=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_OTI6858=m +CONFIG_USB_SERIAL_QUALCOMM=m +CONFIG_USB_SERIAL_SPCP8X5=m +CONFIG_USB_SERIAL_HP4X=m +CONFIG_USB_SERIAL_SAFE=m +CONFIG_USB_SERIAL_SAFE_PADDED=y +CONFIG_USB_SERIAL_SIEMENS_MPI=m +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +CONFIG_USB_SERIAL_SYMBOL=m +CONFIG_USB_SERIAL_TI=m +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_XIRCOM=m +CONFIG_USB_SERIAL_OPTION=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_SERIAL_OPTICON=m +CONFIG_USB_SERIAL_DEBUG=m + +# +# USB Miscellaneous drivers +# +CONFIG_USB_EMI62=m +CONFIG_USB_EMI26=m +CONFIG_USB_ADUTUX=m +CONFIG_USB_SEVSEG=m +CONFIG_USB_RIO500=m +CONFIG_USB_LEGOTOWER=m +CONFIG_USB_LCD=m +CONFIG_USB_BERRY_CHARGE=m +CONFIG_USB_LED=m +CONFIG_USB_CYPRESS_CY7C63=m +CONFIG_USB_CYTHERM=m +CONFIG_USB_IDMOUSE=m +CONFIG_USB_FTDI_ELAN=m +CONFIG_USB_APPLEDISPLAY=m +CONFIG_USB_SISUSBVGA=m +CONFIG_USB_SISUSBVGA_CON=y +CONFIG_USB_LD=m +CONFIG_USB_TRANCEVIBRATOR=m +CONFIG_USB_IOWARRIOR=m +# CONFIG_USB_TEST is not set +CONFIG_USB_ISIGHTFW=m +CONFIG_USB_VST=m +CONFIG_USB_ATM=m +CONFIG_USB_SPEEDTOUCH=m +CONFIG_USB_CXACRU=m +CONFIG_USB_UEAGLEATM=m +CONFIG_USB_XUSBATM=m +# CONFIG_USB_GADGET is not set + +# +# OTG and related infrastructure +# +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_NOP_USB_XCEIV is not set +CONFIG_UWB=m +CONFIG_UWB_HWA=m +CONFIG_UWB_WHCI=m +CONFIG_UWB_WLP=m +CONFIG_UWB_I1480U=m +CONFIG_UWB_I1480U_WLP=m +CONFIG_MMC=m +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_UNSAFE_RESUME is not set + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=m +CONFIG_MMC_BLOCK_BOUNCE=y +CONFIG_SDIO_UART=m +CONFIG_MMC_TEST=m + +# +# MMC/SD/SDIO Host Controller Drivers +# +CONFIG_MMC_SDHCI=m +CONFIG_MMC_SDHCI_PCI=m +CONFIG_MMC_RICOH_MMC=m +CONFIG_MMC_SDHCI_PLTFM=m +CONFIG_MMC_WBSD=m +# CONFIG_MMC_AT91 is not set +# CONFIG_MMC_ATMELMCI is not set +CONFIG_MMC_TIFM_SD=m +CONFIG_MMC_SPI=m +CONFIG_MMC_SDRICOH_CS=m +CONFIG_MMC_CB710=m +CONFIG_MMC_VIA_SDMMC=m +CONFIG_MEMSTICK=m +# CONFIG_MEMSTICK_DEBUG is not set + +# +# MemoryStick drivers +# +# CONFIG_MEMSTICK_UNSAFE_RESUME is not set +CONFIG_MSPRO_BLOCK=m + +# +# MemoryStick Host Controller Drivers +# +CONFIG_MEMSTICK_TIFM_MS=m +CONFIG_MEMSTICK_JMICRON_38X=m +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=m + +# +# LED drivers +# +CONFIG_LEDS_ALIX2=m +CONFIG_LEDS_PCA9532=m +CONFIG_LEDS_GPIO=m +CONFIG_LEDS_GPIO_PLATFORM=y +CONFIG_LEDS_LP3944=m +CONFIG_LEDS_CLEVO_MAIL=m +CONFIG_LEDS_PCA955X=m +CONFIG_LEDS_DAC124S085=m +CONFIG_LEDS_BD2802=m + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=m +CONFIG_LEDS_TRIGGER_IDE_DISK=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=m +CONFIG_LEDS_TRIGGER_BACKLIGHT=m +CONFIG_LEDS_TRIGGER_GPIO=m +CONFIG_LEDS_TRIGGER_DEFAULT_ON=m + +# +# iptables trigger is under Netfilter config (LED target) +# +# CONFIG_ACCESSIBILITY is not set +CONFIG_INFINIBAND=m +CONFIG_INFINIBAND_USER_MAD=m +CONFIG_INFINIBAND_USER_ACCESS=m +CONFIG_INFINIBAND_USER_MEM=y +CONFIG_INFINIBAND_ADDR_TRANS=y +CONFIG_INFINIBAND_MTHCA=m +CONFIG_INFINIBAND_MTHCA_DEBUG=y +CONFIG_INFINIBAND_IPATH=m +CONFIG_INFINIBAND_AMSO1100=m +# CONFIG_INFINIBAND_AMSO1100_DEBUG is not set +CONFIG_INFINIBAND_CXGB3=m +# CONFIG_INFINIBAND_CXGB3_DEBUG is not set +CONFIG_MLX4_INFINIBAND=m +CONFIG_INFINIBAND_NES=m +# CONFIG_INFINIBAND_NES_DEBUG is not set +CONFIG_INFINIBAND_IPOIB=m +CONFIG_INFINIBAND_IPOIB_CM=y +CONFIG_INFINIBAND_IPOIB_DEBUG=y +# CONFIG_INFINIBAND_IPOIB_DEBUG_DATA is not set +CONFIG_INFINIBAND_SRP=m +CONFIG_INFINIBAND_ISER=m +CONFIG_EDAC=y + +# +# Reporting subsystems +# +# CONFIG_EDAC_DEBUG is not set +CONFIG_EDAC_DECODE_MCE=m +CONFIG_EDAC_MM_EDAC=m +CONFIG_EDAC_E752X=m +CONFIG_EDAC_I82975X=m +CONFIG_EDAC_I3000=m +CONFIG_EDAC_I3200=m +CONFIG_EDAC_X38=m +CONFIG_EDAC_I5400=m +CONFIG_EDAC_I5000=m +CONFIG_EDAC_I5100=m +CONFIG_RTC_LIB=m +CONFIG_RTC_CLASS=m + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +CONFIG_RTC_INTF_DEV_UIE_EMUL=y +CONFIG_RTC_DRV_TEST=m + +# +# I2C RTC drivers +# +CONFIG_RTC_DRV_DS1307=m +CONFIG_RTC_DRV_DS1374=m +CONFIG_RTC_DRV_DS1672=m +CONFIG_RTC_DRV_MAX6900=m +CONFIG_RTC_DRV_RS5C372=m +CONFIG_RTC_DRV_ISL1208=m +CONFIG_RTC_DRV_X1205=m +CONFIG_RTC_DRV_PCF8563=m +CONFIG_RTC_DRV_PCF8583=m +CONFIG_RTC_DRV_M41T80=m +CONFIG_RTC_DRV_M41T80_WDT=y +CONFIG_RTC_DRV_S35390A=m +CONFIG_RTC_DRV_FM3130=m +CONFIG_RTC_DRV_RX8581=m +CONFIG_RTC_DRV_RX8025=m + +# +# SPI RTC drivers +# +CONFIG_RTC_DRV_M41T94=m +CONFIG_RTC_DRV_DS1305=m +CONFIG_RTC_DRV_DS1390=m +CONFIG_RTC_DRV_MAX6902=m +CONFIG_RTC_DRV_R9701=m +CONFIG_RTC_DRV_RS5C348=m +CONFIG_RTC_DRV_DS3234=m +CONFIG_RTC_DRV_PCF2123=m + +# +# Platform RTC drivers +# +CONFIG_RTC_DRV_CMOS=m +CONFIG_RTC_DRV_DS1286=m +CONFIG_RTC_DRV_DS1511=m +CONFIG_RTC_DRV_DS1553=m +CONFIG_RTC_DRV_DS1742=m +CONFIG_RTC_DRV_STK17TA8=m +CONFIG_RTC_DRV_M48T86=m +CONFIG_RTC_DRV_M48T35=m +CONFIG_RTC_DRV_M48T59=m +CONFIG_RTC_DRV_BQ4802=m +CONFIG_RTC_DRV_V3020=m +CONFIG_RTC_DRV_AB3100=m + +# +# on-CPU RTC drivers +# +CONFIG_RTC_DRV_PCAP=m +CONFIG_DMADEVICES=y + +# +# DMA Devices +# +CONFIG_ASYNC_TX_DISABLE_CHANNEL_SWITCH=y +CONFIG_INTEL_IOATDMA=m +CONFIG_DMA_ENGINE=y + +# +# DMA Clients +# +CONFIG_NET_DMA=y +CONFIG_ASYNC_TX_DMA=y +CONFIG_DMATEST=m +CONFIG_DCA=m +CONFIG_AUXDISPLAY=y +CONFIG_KS0108=m +CONFIG_KS0108_PORT=0x378 +CONFIG_KS0108_DELAY=2 +CONFIG_CFAG12864B=m +CONFIG_CFAG12864B_RATE=20 +CONFIG_UIO=m +CONFIG_UIO_CIF=m +CONFIG_UIO_PDRV=m +CONFIG_UIO_PDRV_GENIRQ=m +CONFIG_UIO_SMX=m +CONFIG_UIO_AEC=m +CONFIG_UIO_SERCOS3=m +CONFIG_UIO_PCI_GENERIC=m + +# +# TI VLYNQ +# +CONFIG_XEN=y +CONFIG_XEN_INTERFACE_VERSION=0x00030207 + +# +# XEN +# +CONFIG_XEN_PRIVILEGED_GUEST=y +# CONFIG_XEN_UNPRIVILEGED_GUEST is not set +CONFIG_XEN_PRIVCMD=y +CONFIG_XEN_DOMCTL=m +CONFIG_XEN_XENBUS_DEV=y +CONFIG_XEN_NETDEV_ACCEL_SFC_UTIL=m +CONFIG_XEN_BACKEND=m +CONFIG_XEN_BLKDEV_BACKEND=m +CONFIG_XEN_BLKDEV_TAP=m +CONFIG_XEN_BLKDEV_TAP2=m +CONFIG_XEN_BLKBACK_PAGEMAP=m +CONFIG_XEN_NETDEV_BACKEND=m +CONFIG_XEN_NETDEV_TX_SHIFT=10 +# CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set +CONFIG_XEN_NETDEV_ACCEL_SFC_BACKEND=m +CONFIG_XEN_NETDEV_LOOPBACK=m +CONFIG_XEN_PCIDEV_BACKEND=m +CONFIG_XEN_PCIDEV_BACKEND_VPCI=y +# CONFIG_XEN_PCIDEV_BACKEND_PASS is not set +# CONFIG_XEN_PCIDEV_BACKEND_SLOT is not set +# CONFIG_XEN_PCIDEV_BACKEND_CONTROLLER is not set +# CONFIG_XEN_PCIDEV_BE_DEBUG is not set +CONFIG_XEN_TPMDEV_BACKEND=m +CONFIG_XEN_SCSI_BACKEND=m +CONFIG_XEN_USB_BACKEND=m +CONFIG_XEN_BLKDEV_FRONTEND=m +CONFIG_XEN_NETDEV_FRONTEND=m +CONFIG_XEN_NETDEV_ACCEL_SFC_FRONTEND=m +CONFIG_XEN_SCSI_FRONTEND=m +CONFIG_XEN_USB_FRONTEND=m +# CONFIG_XEN_USB_FRONTEND_HCD_STATS is not set +# CONFIG_XEN_USB_FRONTEND_HCD_PM is not set +CONFIG_XEN_GRANT_DEV=m +CONFIG_XEN_FRAMEBUFFER=y +CONFIG_XEN_KEYBOARD=y +# CONFIG_XEN_DISABLE_SERIAL is not set +CONFIG_XEN_SYSFS=y +CONFIG_XEN_NR_GUEST_DEVICES=2048 +# CONFIG_XEN_COMPAT_030002_AND_LATER is not set +# CONFIG_XEN_COMPAT_030004_AND_LATER is not set +# CONFIG_XEN_COMPAT_030100_AND_LATER is not set +CONFIG_XEN_COMPAT_030200_AND_LATER=y +# CONFIG_XEN_COMPAT_030300_AND_LATER is not set +# CONFIG_XEN_COMPAT_030400_AND_LATER is not set +# CONFIG_XEN_COMPAT_LATEST_ONLY is not set +CONFIG_XEN_COMPAT=0x030200 +CONFIG_XEN_VCPU_INFO_PLACEMENT=y +CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y +CONFIG_IRQ_PER_CPU=y +CONFIG_NO_IDLE_HZ=y +CONFIG_XEN_SMPBOOT=y +CONFIG_XEN_DEVMEM=y +CONFIG_XEN_BALLOON=y +CONFIG_XEN_SCRUB_PAGES=y +CONFIG_STAGING=y +# CONFIG_STAGING_EXCLUDE_BUILD is not set +CONFIG_ET131X=m +# CONFIG_ET131X_DEBUG is not set +CONFIG_SLICOSS=m +CONFIG_VIDEO_GO7007=m +CONFIG_VIDEO_GO7007_USB=m +CONFIG_VIDEO_GO7007_USB_S2250_BOARD=m +CONFIG_VIDEO_GO7007_OV7640=m +CONFIG_VIDEO_GO7007_SAA7113=m +CONFIG_VIDEO_GO7007_SAA7115=m +CONFIG_VIDEO_GO7007_TW9903=m +CONFIG_VIDEO_GO7007_UDA1342=m +CONFIG_VIDEO_GO7007_SONY_TUNER=m +CONFIG_VIDEO_GO7007_TW2804=m +CONFIG_VIDEO_CX25821=m +CONFIG_VIDEO_CX25821_ALSA=m +CONFIG_USB_IP_COMMON=m +CONFIG_USB_IP_VHCI_HCD=m +CONFIG_USB_IP_HOST=m +CONFIG_W35UND=m +CONFIG_PRISM2_USB=m +CONFIG_ECHO=m +CONFIG_POCH=m +CONFIG_OTUS=m +CONFIG_RT2860=m +CONFIG_RT2870=m +CONFIG_RT3090=m +# CONFIG_COMEDI is not set +CONFIG_ASUS_OLED=m +CONFIG_PANEL=m +CONFIG_PANEL_PARPORT=0 +CONFIG_PANEL_PROFILE=5 +# CONFIG_PANEL_CHANGE_MESSAGE is not set +CONFIG_ALTERA_PCIE_CHDMA=m +CONFIG_RTL8187SE=m +CONFIG_RTL8192SU=m +CONFIG_RTL8192E=m +CONFIG_TRANZPORT=m + +# +# Android +# + +# +# Qualcomm MSM Camera And Video +# + +# +# Camera Sensor Selection +# +CONFIG_INPUT_GPIO=m +CONFIG_DST=m +# CONFIG_DST_DEBUG is not set +CONFIG_POHMELFS=m +# CONFIG_POHMELFS_DEBUG is not set +CONFIG_POHMELFS_CRYPTO=y +CONFIG_B3DFG=m +CONFIG_IDE_PHISON=m +CONFIG_PLAN9AUTH=m +CONFIG_LINE6_USB=m +# CONFIG_DRM_RADEON_KMS is not set +CONFIG_USB_SERIAL_QUATECH2=m +CONFIG_USB_SERIAL_QUATECH_USB2=m +CONFIG_VT6655=m +CONFIG_VT6656=m +CONFIG_FB_UDL=m +CONFIG_VME_BUS=m + +# +# VME Bridge Drivers +# +CONFIG_VME_CA91CX42=m +CONFIG_VME_TSI148=m + +# +# VME Device Drivers +# +CONFIG_VME_USER=m + +# +# RAR Register Driver +# +CONFIG_RAR_REGISTER=m +CONFIG_DX_SEP=m +CONFIG_IIO=m +CONFIG_IIO_RING_BUFFER=y +CONFIG_IIO_SW_RING=m +CONFIG_IIO_TRIGGER=y + +# +# Accelerometers +# +CONFIG_KXSD9=m +CONFIG_LIS3L02DQ=m +CONFIG_SCA3000=m + +# +# Analog to digital convertors +# +CONFIG_MAX1363=m + +# +# Light sensors +# +CONFIG_TSL2561=m + +# +# Triggers - standalone +# +CONFIG_IIO_PERIODIC_RTC_TRIGGER=m +CONFIG_IIO_GPIO_TRIGGER=m +CONFIG_X86_PLATFORM_DEVICES=y +CONFIG_ACER_WMI=m +CONFIG_ACERHDF=m +CONFIG_ASUS_LAPTOP=m +CONFIG_DELL_WMI=m +CONFIG_FUJITSU_LAPTOP=m +# CONFIG_FUJITSU_LAPTOP_DEBUG is not set +CONFIG_HP_WMI=m +CONFIG_MSI_LAPTOP=m +CONFIG_PANASONIC_LAPTOP=m +CONFIG_COMPAL_LAPTOP=m +CONFIG_SONY_LAPTOP=m +CONFIG_SONYPI_COMPAT=y +CONFIG_THINKPAD_ACPI=m +# CONFIG_THINKPAD_ACPI_DEBUGFACILITIES is not set +# CONFIG_THINKPAD_ACPI_DEBUG is not set +# CONFIG_THINKPAD_ACPI_UNSAFE_LEDS is not set +CONFIG_THINKPAD_ACPI_VIDEO=y +CONFIG_THINKPAD_ACPI_HOTKEY_POLL=y +CONFIG_INTEL_MENLOW=m +CONFIG_EEEPC_LAPTOP=m +CONFIG_ACPI_WMI=m +# CONFIG_ACPI_ASUS is not set +CONFIG_TOPSTAR_LAPTOP=m +CONFIG_ACPI_TOSHIBA=m + +# +# Firmware Drivers +# +CONFIG_EDD=m +# CONFIG_EDD_OFF is not set +CONFIG_FIRMWARE_MEMMAP=y +CONFIG_DELL_RBU=m +CONFIG_DCDBAS=m +CONFIG_DMIID=y +CONFIG_ISCSI_IBFT_FIND=y +CONFIG_ISCSI_IBFT=m + +# +# File systems +# +CONFIG_EXT2_FS=m +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=m +CONFIG_EXT3_DEFAULTS_TO_ORDERED=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_EXT4_FS=m +CONFIG_EXT4_FS_XATTR=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +# CONFIG_EXT4_DEBUG is not set +CONFIG_JBD=m +# CONFIG_JBD_DEBUG is not set +CONFIG_JBD2=m +# CONFIG_JBD2_DEBUG is not set +CONFIG_FS_MBCACHE=m +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +CONFIG_REISERFS_FS_XATTR=y +CONFIG_REISERFS_FS_POSIX_ACL=y +CONFIG_REISERFS_FS_SECURITY=y +CONFIG_JFS_FS=m +CONFIG_JFS_POSIX_ACL=y +CONFIG_JFS_SECURITY=y +# CONFIG_JFS_DEBUG is not set +CONFIG_JFS_STATISTICS=y +CONFIG_FS_POSIX_ACL=y +CONFIG_XFS_FS=m +CONFIG_XFS_QUOTA=y +CONFIG_XFS_POSIX_ACL=y +CONFIG_XFS_RT=y +# CONFIG_XFS_DEBUG is not set +CONFIG_GFS2_FS=m +# CONFIG_GFS2_FS_LOCKING_DLM is not set +CONFIG_OCFS2_FS=m +CONFIG_OCFS2_FS_O2CB=m +CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m +CONFIG_OCFS2_FS_STATS=y +CONFIG_OCFS2_DEBUG_MASKLOG=y +# CONFIG_OCFS2_DEBUG_FS is not set +# CONFIG_OCFS2_FS_POSIX_ACL is not set +CONFIG_BTRFS_FS=m +CONFIG_BTRFS_FS_POSIX_ACL=y +CONFIG_NILFS2_FS=m +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y +CONFIG_DNOTIFY=y +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_QUOTA=y +CONFIG_QUOTA_NETLINK_INTERFACE=y +CONFIG_PRINT_QUOTA_WARNING=y +CONFIG_QUOTA_TREE=m +CONFIG_QFMT_V1=m +CONFIG_QFMT_V2=m +CONFIG_QUOTACTL=y +CONFIG_AUTOFS_FS=m +CONFIG_AUTOFS4_FS=m +CONFIG_FUSE_FS=m +CONFIG_CUSE=m +CONFIG_GENERIC_ACL=y + +# +# Caches +# +CONFIG_FSCACHE=m +CONFIG_FSCACHE_STATS=y +# CONFIG_FSCACHE_HISTOGRAM is not set +# CONFIG_FSCACHE_DEBUG is not set +CONFIG_FSCACHE_OBJECT_LIST=y +CONFIG_CACHEFILES=m +# CONFIG_CACHEFILES_DEBUG is not set +# CONFIG_CACHEFILES_HISTOGRAM is not set + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_CONFIGFS_FS=m +CONFIG_MISC_FILESYSTEMS=y +CONFIG_ADFS_FS=m +CONFIG_ADFS_FS_RW=y +CONFIG_AFFS_FS=m +CONFIG_ECRYPT_FS=m +CONFIG_HFS_FS=m +CONFIG_HFSPLUS_FS=m +CONFIG_BEFS_FS=m +# CONFIG_BEFS_DEBUG is not set +CONFIG_BFS_FS=m +CONFIG_EFS_FS=m +CONFIG_JFFS2_FS=m +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +CONFIG_JFFS2_SUMMARY=y +CONFIG_JFFS2_FS_XATTR=y +CONFIG_JFFS2_FS_POSIX_ACL=y +CONFIG_JFFS2_FS_SECURITY=y +CONFIG_JFFS2_COMPRESSION_OPTIONS=y +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_JFFS2_CMODE_NONE is not set +CONFIG_JFFS2_CMODE_PRIORITY=y +# CONFIG_JFFS2_CMODE_SIZE is not set +# CONFIG_JFFS2_CMODE_FAVOURLZO is not set +CONFIG_UBIFS_FS=m +CONFIG_UBIFS_FS_XATTR=y +CONFIG_UBIFS_FS_ADVANCED_COMPR=y +CONFIG_UBIFS_FS_LZO=y +CONFIG_UBIFS_FS_ZLIB=y +# CONFIG_UBIFS_FS_DEBUG is not set +CONFIG_CRAMFS=m +CONFIG_SQUASHFS=m +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +CONFIG_VXFS_FS=m +CONFIG_MINIX_FS=m +CONFIG_OMFS_FS=m +CONFIG_HPFS_FS=m +CONFIG_QNX4FS_FS=m +CONFIG_ROMFS_FS=m +# CONFIG_ROMFS_BACKED_BY_BLOCK is not set +# CONFIG_ROMFS_BACKED_BY_MTD is not set +CONFIG_ROMFS_BACKED_BY_BOTH=y +CONFIG_ROMFS_ON_BLOCK=y +CONFIG_ROMFS_ON_MTD=y +CONFIG_SYSV_FS=m +CONFIG_UFS_FS=m +CONFIG_UFS_FS_WRITE=y +# CONFIG_UFS_DEBUG is not set +CONFIG_EXOFS_FS=m +# CONFIG_EXOFS_DEBUG is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +# CONFIG_NFS_V4_1 is not set +CONFIG_NFS_FSCACHE=y +CONFIG_NFSD=m +CONFIG_NFSD_V2_ACL=y +CONFIG_NFSD_V3=y +CONFIG_NFSD_V3_ACL=y +CONFIG_NFSD_V4=y +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +CONFIG_NFS_ACL_SUPPORT=m +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=m +CONFIG_SUNRPC_GSS=m +CONFIG_SUNRPC_XPRT_RDMA=m +CONFIG_RPCSEC_GSS_KRB5=m +CONFIG_RPCSEC_GSS_SPKM3=m +# CONFIG_SMB_FS is not set +CONFIG_CIFS=m +CONFIG_CIFS_STATS=y +CONFIG_CIFS_STATS2=y +CONFIG_CIFS_WEAK_PW_HASH=y +CONFIG_CIFS_UPCALL=y +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +# CONFIG_CIFS_DEBUG2 is not set +CONFIG_CIFS_DFS_UPCALL=y +CONFIG_CIFS_EXPERIMENTAL=y +CONFIG_NCP_FS=m +CONFIG_NCPFS_PACKET_SIGNING=y +CONFIG_NCPFS_IOCTL_LOCKING=y +CONFIG_NCPFS_STRONG=y +CONFIG_NCPFS_NFS_NS=y +CONFIG_NCPFS_OS2_NS=y +CONFIG_NCPFS_SMALLDOS=y +CONFIG_NCPFS_NLS=y +CONFIG_NCPFS_EXTRAS=y +CONFIG_CODA_FS=m +CONFIG_AFS_FS=m +# CONFIG_AFS_DEBUG is not set +CONFIG_AFS_FSCACHE=y +CONFIG_9P_FS=m +# CONFIG_9P_FSCACHE is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +CONFIG_OSF_PARTITION=y +# CONFIG_AMIGA_PARTITION is not set +CONFIG_ATARI_PARTITION=y +CONFIG_MAC_PARTITION=y +CONFIG_MSDOS_PARTITION=y +CONFIG_BSD_DISKLABEL=y +# CONFIG_MINIX_SUBPARTITION is not set +CONFIG_SOLARIS_X86_PARTITION=y +CONFIG_UNIXWARE_DISKLABEL=y +CONFIG_LDM_PARTITION=y +# CONFIG_LDM_DEBUG is not set +CONFIG_SGI_PARTITION=y +CONFIG_ULTRIX_PARTITION=y +CONFIG_SUN_PARTITION=y +CONFIG_KARMA_PARTITION=y +CONFIG_EFI_PARTITION=y +CONFIG_SYSV68_PARTITION=y +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=m +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_ASCII=m +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_NLS_UTF8=m +CONFIG_DLM=m +CONFIG_DLM_DEBUG=y + +# +# Kernel hacking +# +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_PRINTK_TIME=y +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=2048 +CONFIG_MAGIC_SYSRQ=y +CONFIG_STRIP_ASM_SYMS=y +CONFIG_UNUSED_SYMBOLS=y +CONFIG_DEBUG_FS=y +CONFIG_HEADERS_CHECK=y +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +# CONFIG_DETECT_SOFTLOCKUP is not set +CONFIG_DETECT_HUNG_TASK=y +# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set +CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 +CONFIG_SCHED_DEBUG=y +CONFIG_SCHEDSTATS=y +CONFIG_TIMER_STATS=y +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +CONFIG_STACKTRACE=y +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_VIRTUAL is not set +# CONFIG_DEBUG_WRITECOUNT is not set +CONFIG_DEBUG_MEMORY_INIT=y +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set +CONFIG_ARCH_WANT_FRAME_POINTERS=y +CONFIG_FRAME_POINTER=y +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_KPROBES_SANITY_TEST is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +CONFIG_DEBUG_BLOCK_EXT_DEVT=y +CONFIG_DEBUG_FORCE_WEAK_PER_CPU=y +CONFIG_LKDTM=m +# CONFIG_FAULT_INJECTION is not set +CONFIG_LATENCYTOP=y +CONFIG_SYSCTL_SYSCALL_CHECK=y +# CONFIG_DEBUG_PAGEALLOC is not set +CONFIG_USER_STACKTRACE_SUPPORT=y +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_FP_TEST=y +CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_SYSCALL_TRACEPOINTS=y +CONFIG_RING_BUFFER=y +CONFIG_RING_BUFFER_ALLOW_SWAP=y +CONFIG_TRACING_SUPPORT=y +# CONFIG_FTRACE is not set +CONFIG_PROVIDE_OHCI1394_DMA_INIT=y +CONFIG_BUILD_DOCSRC=y +CONFIG_DYNAMIC_DEBUG=y +# CONFIG_DMA_API_DEBUG is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KMEMCHECK=y +# CONFIG_KMEMCHECK is not set +# CONFIG_STRICT_DEVMEM is not set +CONFIG_EARLY_PRINTK=y +CONFIG_EARLY_PRINTK_DBGP=y +# CONFIG_DEBUG_STACKOVERFLOW is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_PER_CPU_MAPS is not set +# CONFIG_X86_PTDUMP is not set +CONFIG_DEBUG_RODATA=y +# CONFIG_DEBUG_RODATA_TEST is not set +# CONFIG_DEBUG_NX_TEST is not set +# CONFIG_IOMMU_STRESS is not set +CONFIG_IO_DELAY_TYPE_0X80=0 +CONFIG_IO_DELAY_TYPE_0XED=1 +CONFIG_IO_DELAY_TYPE_UDELAY=2 +CONFIG_IO_DELAY_TYPE_NONE=3 +CONFIG_IO_DELAY_0X80=y +# CONFIG_IO_DELAY_0XED is not set +# CONFIG_IO_DELAY_UDELAY is not set +# CONFIG_IO_DELAY_NONE is not set +CONFIG_DEFAULT_IO_DELAY_TYPE=0 +CONFIG_OPTIMIZE_INLINING=y + +# +# Security options +# +CONFIG_KEYS=y +# CONFIG_KEYS_DEBUG_PROC_KEYS is not set +CONFIG_SECURITY=y +CONFIG_SECURITYFS=y +CONFIG_SECURITY_NETWORK=y +CONFIG_SECURITY_NETWORK_XFRM=y +CONFIG_SECURITY_PATH=y +CONFIG_SECURITY_FILE_CAPABILITIES=y +CONFIG_LSM_MMAP_MIN_ADDR=0 +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=0 +CONFIG_SECURITY_SELINUX_DISABLE=y +CONFIG_SECURITY_SELINUX_DEVELOP=y +CONFIG_SECURITY_SELINUX_AVC_STATS=y +CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1 +# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set +# CONFIG_SECURITY_SMACK is not set +# CONFIG_SECURITY_TOMOYO is not set +# CONFIG_IMA is not set +CONFIG_XOR_BLOCKS=m +CONFIG_ASYNC_CORE=m +CONFIG_ASYNC_MEMCPY=m +CONFIG_ASYNC_XOR=m +CONFIG_ASYNC_PQ=m +CONFIG_ASYNC_RAID6_RECOV=m +CONFIG_ASYNC_TX_DISABLE_PQ_VAL_DMA=y +CONFIG_ASYNC_TX_DISABLE_XOR_VAL_DMA=y +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +CONFIG_CRYPTO_FIPS=y +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD=m +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER=m +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG=m +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_PCOMP=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +CONFIG_CRYPTO_GF128MUL=m +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_WORKQUEUE=y +CONFIG_CRYPTO_CRYPTD=m +CONFIG_CRYPTO_AUTHENC=m +CONFIG_CRYPTO_TEST=m + +# +# Authenticated Encryption with Associated Data +# +CONFIG_CRYPTO_CCM=m +CONFIG_CRYPTO_GCM=m +CONFIG_CRYPTO_SEQIV=m + +# +# Block modes +# +CONFIG_CRYPTO_CBC=m +CONFIG_CRYPTO_CTR=m +CONFIG_CRYPTO_CTS=m +CONFIG_CRYPTO_ECB=m +CONFIG_CRYPTO_LRW=m +CONFIG_CRYPTO_PCBC=m +CONFIG_CRYPTO_XTS=m +CONFIG_CRYPTO_FPU=m + +# +# Hash modes +# +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_XCBC=m +CONFIG_CRYPTO_VMAC=m + +# +# Digest +# +CONFIG_CRYPTO_CRC32C=m +CONFIG_CRYPTO_CRC32C_INTEL=m +CONFIG_CRYPTO_GHASH=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=m +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_RMD128=m +CONFIG_CRYPTO_RMD160=m +CONFIG_CRYPTO_RMD256=m +CONFIG_CRYPTO_RMD320=m +CONFIG_CRYPTO_SHA1=m +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_WP512=m + +# +# Ciphers +# +CONFIG_CRYPTO_AES=m +CONFIG_CRYPTO_AES_X86_64=m +CONFIG_CRYPTO_AES_NI_INTEL=m +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_CAMELLIA=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_DES=m +CONFIG_CRYPTO_FCRYPT=m +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_SALSA20=m +CONFIG_CRYPTO_SALSA20_X86_64=m +CONFIG_CRYPTO_SEED=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_TEA=m +# CONFIG_CRYPTO_TWOFISH is not set +CONFIG_CRYPTO_TWOFISH_COMMON=m +CONFIG_CRYPTO_TWOFISH_X86_64=m + +# +# Compression +# +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_ZLIB=m +CONFIG_CRYPTO_LZO=m + +# +# Random Number Generation +# +CONFIG_CRYPTO_ANSI_CPRNG=m +CONFIG_CRYPTO_HW=y +CONFIG_CRYPTO_DEV_PADLOCK=m +CONFIG_CRYPTO_DEV_PADLOCK_AES=m +CONFIG_CRYPTO_DEV_PADLOCK_SHA=m +CONFIG_CRYPTO_DEV_HIFN_795X=m +CONFIG_CRYPTO_DEV_HIFN_795X_RNG=y +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_FIRST_BIT=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_GENERIC_FIND_LAST_BIT=y +CONFIG_CRC_CCITT=m +CONFIG_CRC16=m +CONFIG_CRC_T10DIF=m +CONFIG_CRC_ITU_T=m +CONFIG_CRC32=y +CONFIG_CRC7=m +CONFIG_LIBCRC32C=m +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=m +CONFIG_LZO_COMPRESS=m +CONFIG_LZO_DECOMPRESS=m +CONFIG_DECOMPRESS_GZIP=y +CONFIG_DECOMPRESS_BZIP2=y +CONFIG_DECOMPRESS_LZMA=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_REED_SOLOMON=m +CONFIG_REED_SOLOMON_DEC16=y +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_CHECK_SIGNATURE=y +CONFIG_NLATTR=y diff --git a/xen-balloon-max-target b/xen-balloon-max-target new file mode 100644 index 0000000..0b0710d --- /dev/null +++ b/xen-balloon-max-target @@ -0,0 +1,78 @@ +From: ccoffing@novell.com +Subject: Expose min/max limits of domain ballooning +Patch-mainline: obsolete +References: 152667, 184727 + +jb: Also added this to the sysfs representation. + +--- sle11sp1-2010-02-02.orig/drivers/xen/balloon/balloon.c 2010-02-02 14:56:27.000000000 +0100 ++++ sle11sp1-2010-02-02/drivers/xen/balloon/balloon.c 2010-02-02 15:08:54.000000000 +0100 +@@ -239,7 +239,7 @@ static unsigned long current_target(void + return target; + } + +-static unsigned long minimum_target(void) ++unsigned long balloon_minimum_target(void) + { + #ifndef CONFIG_XEN + #define max_pfn num_physpages +@@ -461,7 +461,7 @@ static void balloon_process(struct work_ + void balloon_set_new_target(unsigned long target) + { + /* No need for lock. Not read-modify-write updates. */ +- bs.target_pages = max(target, minimum_target()); ++ bs.target_pages = max(target, balloon_minimum_target()); + schedule_work(&balloon_worker); + } + +@@ -536,10 +536,13 @@ static int balloon_read(char *page, char + page, + "Current allocation: %8lu kB\n" + "Requested target: %8lu kB\n" ++ "Minimum target: %8lu kB\n" ++ "Maximum target: %8lu kB\n" + "Low-mem balloon: %8lu kB\n" + "High-mem balloon: %8lu kB\n" + "Driver pages: %8lu kB\n", + PAGES2KB(bs.current_pages), PAGES2KB(bs.target_pages), ++ PAGES2KB(balloon_minimum_target()), PAGES2KB(num_physpages), + PAGES2KB(bs.balloon_low), PAGES2KB(bs.balloon_high), + PAGES2KB(bs.driver_pages)); + +--- sle11sp1-2010-02-02.orig/drivers/xen/balloon/common.h 2009-06-09 15:01:37.000000000 +0200 ++++ sle11sp1-2010-02-02/drivers/xen/balloon/common.h 2009-08-19 10:36:49.000000000 +0200 +@@ -52,5 +52,6 @@ int balloon_sysfs_init(void); + void balloon_sysfs_exit(void); + + void balloon_set_new_target(unsigned long target); ++unsigned long balloon_minimum_target(void); + + #endif /* __XEN_BALLOON_COMMON_H__ */ +--- sle11sp1-2010-02-02.orig/drivers/xen/balloon/sysfs.c 2009-11-06 10:51:55.000000000 +0100 ++++ sle11sp1-2010-02-02/drivers/xen/balloon/sysfs.c 2009-08-19 10:36:47.000000000 +0200 +@@ -31,6 +31,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -53,6 +54,8 @@ + static SYSDEV_ATTR(name, S_IRUGO, show_##name, NULL) + + BALLOON_SHOW(current_kb, "%lu\n", PAGES2KB(bs.current_pages)); ++BALLOON_SHOW(min_kb, "%lu\n", PAGES2KB(balloon_minimum_target())); ++BALLOON_SHOW(max_kb, "%lu\n", PAGES2KB(num_physpages)); + BALLOON_SHOW(low_kb, "%lu\n", PAGES2KB(bs.balloon_low)); + BALLOON_SHOW(high_kb, "%lu\n", PAGES2KB(bs.balloon_high)); + BALLOON_SHOW(driver_kb, "%lu\n", PAGES2KB(bs.driver_pages)); +@@ -123,6 +126,8 @@ static struct sysdev_attribute *balloon_ + + static struct attribute *balloon_info_attrs[] = { + &attr_current_kb.attr, ++ &attr_min_kb.attr, ++ &attr_max_kb.attr, + &attr_low_kb.attr, + &attr_high_kb.attr, + &attr_driver_kb.attr, diff --git a/xen-blkback-bimodal-suse b/xen-blkback-bimodal-suse new file mode 100644 index 0000000..3080f2a --- /dev/null +++ b/xen-blkback-bimodal-suse @@ -0,0 +1,39 @@ +Subject: backward compatibility +From: Gerd Hoffmann +Patch-mainline: obsolete + +--- + linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c | 6 ++++++ + linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c | 6 ++++++ + 2 files changed, 12 insertions(+) + +--- sle11sp1-2010-03-22.orig/drivers/xen/blkback/xenbus.c 2010-03-22 12:26:08.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/xen/blkback/xenbus.c 2010-03-22 12:53:24.000000000 +0100 +@@ -500,6 +500,12 @@ static int connect_ring(struct backend_i + be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_32; + else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_X86_64)) + be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_64; ++#if 1 /* maintain compatibility with early sles10-sp1 and paravirt netware betas */ ++ else if (0 == strcmp(protocol, "1")) ++ be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_32; ++ else if (0 == strcmp(protocol, "2")) ++ be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_64; ++#endif + else { + xenbus_dev_fatal(dev, err, "unknown fe protocol %s", protocol); + return -1; +--- sle11sp1-2010-03-22.orig/drivers/xen/blktap/xenbus.c 2010-01-27 14:48:30.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/xen/blktap/xenbus.c 2010-01-27 14:59:26.000000000 +0100 +@@ -440,6 +440,12 @@ static int connect_ring(struct backend_i + be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_32; + else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_X86_64)) + be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_64; ++#if 1 /* maintain compatibility with early sles10-sp1 and paravirt netware betas */ ++ else if (0 == strcmp(protocol, "1")) ++ be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_32; ++ else if (0 == strcmp(protocol, "2")) ++ be->blkif->blk_protocol = BLKIF_PROTOCOL_X86_64; ++#endif + else { + xenbus_dev_fatal(dev, err, "unknown fe protocol %s", protocol); + return -1; diff --git a/xen-blkback-cdrom b/xen-blkback-cdrom new file mode 100644 index 0000000..9b2907b --- /dev/null +++ b/xen-blkback-cdrom @@ -0,0 +1,233 @@ +Subject: CDROM removable media-present attribute plus handling code +From: plc@novell.com +Patch-mainline: obsolete +References: 159907 + +--- sle11sp1-2010-03-22.orig/drivers/xen/blkback/Makefile 2009-06-09 15:01:37.000000000 +0200 ++++ sle11sp1-2010-03-22/drivers/xen/blkback/Makefile 2009-06-09 15:50:31.000000000 +0200 +@@ -1,4 +1,4 @@ + obj-$(CONFIG_XEN_BLKDEV_BACKEND) := blkbk.o + obj-$(CONFIG_XEN_BLKBACK_PAGEMAP) += blkback-pagemap.o + +-blkbk-y := blkback.o xenbus.o interface.o vbd.o ++blkbk-y := blkback.o xenbus.o interface.o vbd.o cdrom.o +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/drivers/xen/blkback/cdrom.c 2010-03-22 12:54:41.000000000 +0100 +@@ -0,0 +1,162 @@ ++/****************************************************************************** ++ * blkback/cdrom.c ++ * ++ * Routines for managing cdrom watch and media-present attribute of a ++ * cdrom type virtual block device (VBD). ++ * ++ * Copyright (c) 2003-2005, Keir Fraser & Steve Hand ++ * Copyright (c) 2007 Pat Campbell ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License version 2 ++ * as published by the Free Software Foundation; or, when distributed ++ * separately from the Linux kernel or incorporated into other ++ * software packages, subject to the following license: ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this source file (the "Software"), to deal in the Software without ++ * restriction, including without limitation the rights to use, copy, modify, ++ * merge, publish, distribute, sublicense, and/or sell copies of the Software, ++ * and to permit persons to whom the Software is furnished to do so, subject to ++ * the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS ++ * IN THE SOFTWARE. ++ */ ++ ++#include "common.h" ++ ++#undef DPRINTK ++#define DPRINTK(_f, _a...) \ ++ printk("(%s() file=%s, line=%d) " _f "\n", \ ++ __PRETTY_FUNCTION__, __FILE__ , __LINE__ , ##_a ) ++ ++ ++#define MEDIA_PRESENT "media-present" ++ ++static void cdrom_media_changed(struct xenbus_watch *, const char **, unsigned int); ++ ++/** ++ * Writes media-present=1 attribute for the given vbd device if not ++ * already there ++ */ ++static int cdrom_xenstore_write_media_present(struct backend_info *be) ++{ ++ struct xenbus_device *dev = be->dev; ++ struct xenbus_transaction xbt; ++ int err; ++ int media_present; ++ ++ err = xenbus_scanf(XBT_NIL, dev->nodename, MEDIA_PRESENT, "%d", ++ &media_present); ++ if (0 < err) { ++ DPRINTK("already written err%d", err); ++ return(0); ++ } ++ media_present = 1; ++ ++again: ++ err = xenbus_transaction_start(&xbt); ++ if (err) { ++ xenbus_dev_fatal(dev, err, "starting transaction"); ++ return(-1); ++ } ++ ++ err = xenbus_printf(xbt, dev->nodename, MEDIA_PRESENT, "%d", media_present ); ++ if (err) { ++ xenbus_dev_fatal(dev, err, "writing %s/%s", ++ dev->nodename, MEDIA_PRESENT); ++ goto abort; ++ } ++ err = xenbus_transaction_end(xbt, 0); ++ if (err == -EAGAIN) ++ goto again; ++ if (err) ++ xenbus_dev_fatal(dev, err, "ending transaction"); ++ return 0; ++ abort: ++ xenbus_transaction_end(xbt, 1); ++ return -1; ++} ++ ++/** ++ * ++ */ ++static int cdrom_is_type(struct backend_info *be) ++{ ++ DPRINTK("type:%x", be->blkif->vbd.type ); ++ return (be->blkif->vbd.type & VDISK_CDROM) ++ && (be->blkif->vbd.type & GENHD_FL_REMOVABLE); ++} ++ ++/** ++ * ++ */ ++void cdrom_add_media_watch(struct backend_info *be) ++{ ++ struct xenbus_device *dev = be->dev; ++ int err; ++ ++ DPRINTK("nodename:%s", dev->nodename); ++ if (cdrom_is_type(be)) { ++ DPRINTK("is a cdrom"); ++ if ( cdrom_xenstore_write_media_present(be) == 0 ) { ++ DPRINTK( "xenstore wrote OK"); ++ err = xenbus_watch_path2(dev, dev->nodename, MEDIA_PRESENT, ++ &be->cdrom_watch, ++ cdrom_media_changed); ++ if (err) ++ DPRINTK( "media_present watch add failed" ); ++ } ++ } ++} ++ ++/** ++ * Callback received when the "media_present" xenstore node is changed ++ */ ++static void cdrom_media_changed(struct xenbus_watch *watch, ++ const char **vec, unsigned int len) ++{ ++ int err; ++ unsigned media_present; ++ struct backend_info *be ++ = container_of(watch, struct backend_info, cdrom_watch); ++ struct xenbus_device *dev = be->dev; ++ ++ if (!cdrom_is_type(be)) { ++ DPRINTK("callback not for a cdrom" ); ++ return; ++ } ++ ++ err = xenbus_scanf(XBT_NIL, dev->nodename, MEDIA_PRESENT, "%d", ++ &media_present); ++ if (err == 0 || err == -ENOENT) { ++ DPRINTK("xenbus_read of cdrom media_present node error:%d",err); ++ return; ++ } ++ ++ if (media_present == 0) ++ vbd_free(&be->blkif->vbd); ++ else { ++ char *p = strrchr(dev->otherend, '/') + 1; ++ long handle = simple_strtoul(p, NULL, 0); ++ ++ if (!be->blkif->vbd.bdev) { ++ err = vbd_create(be->blkif, handle, be->major, be->minor, ++ !strchr(be->mode, 'w'), 1); ++ if (err) { ++ be->major = be->minor = 0; ++ xenbus_dev_fatal(dev, err, "creating vbd structure"); ++ return; ++ } ++ } ++ } ++} +--- sle11sp1-2010-03-22.orig/drivers/xen/blkback/common.h 2010-03-22 12:20:19.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/xen/blkback/common.h 2010-03-22 12:54:11.000000000 +0100 +@@ -106,6 +106,7 @@ struct backend_info + struct xenbus_device *dev; + blkif_t *blkif; + struct xenbus_watch backend_watch; ++ struct xenbus_watch cdrom_watch; + unsigned major; + unsigned minor; + char *mode; +@@ -152,4 +153,7 @@ int blkif_schedule(void *arg); + int blkback_barrier(struct xenbus_transaction xbt, + struct backend_info *be, int state); + ++/* cdrom media change */ ++void cdrom_add_media_watch(struct backend_info *be); ++ + #endif /* __BLKIF__BACKEND__COMMON_H__ */ +--- sle11sp1-2010-03-22.orig/drivers/xen/blkback/vbd.c 2009-11-06 10:52:09.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/xen/blkback/vbd.c 2010-03-22 12:53:45.000000000 +0100 +@@ -108,6 +108,9 @@ int vbd_translate(struct phys_req *req, + if ((operation != READ) && vbd->readonly) + goto out; + ++ if (vbd->bdev == NULL) ++ goto out; ++ + if (unlikely((req->sector_number + req->nr_sects) > vbd_sz(vbd))) + goto out; + +--- sle11sp1-2010-03-22.orig/drivers/xen/blkback/xenbus.c 2010-03-22 12:53:34.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/xen/blkback/xenbus.c 2010-03-22 12:54:58.000000000 +0100 +@@ -187,6 +187,12 @@ static int blkback_remove(struct xenbus_ + be->backend_watch.node = NULL; + } + ++ if (be->cdrom_watch.node) { ++ unregister_xenbus_watch(&be->cdrom_watch); ++ kfree(be->cdrom_watch.node); ++ be->cdrom_watch.node = NULL; ++ } ++ + if (be->blkif) { + blkif_disconnect(be->blkif); + vbd_free(&be->blkif->vbd); +@@ -343,6 +349,9 @@ static void backend_changed(struct xenbu + + /* We're potentially connected now */ + update_blkif_status(be->blkif); ++ ++ /* Add watch for cdrom media status if necessay */ ++ cdrom_add_media_watch(be); + } + } + diff --git a/xen-blkfront-cdrom b/xen-blkfront-cdrom new file mode 100644 index 0000000..935af0e --- /dev/null +++ b/xen-blkfront-cdrom @@ -0,0 +1,711 @@ +From: plc@novell.com +Subject: implement forwarding of CD-ROM specific commands +Patch-mainline: obsolete +References: fate#300964 + +--- sle11sp1-2010-03-22.orig/drivers/cdrom/Makefile 2010-03-22 12:07:53.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/cdrom/Makefile 2009-10-15 12:13:13.000000000 +0200 +@@ -9,6 +9,7 @@ obj-$(CONFIG_BLK_DEV_IDECD) += + obj-$(CONFIG_BLK_DEV_SR) += cdrom.o + obj-$(CONFIG_PARIDE_PCD) += cdrom.o + obj-$(CONFIG_CDROM_PKTCDVD) += cdrom.o ++obj-$(CONFIG_XEN_BLKDEV_FRONTEND) += cdrom.o + + obj-$(CONFIG_VIOCD) += viocd.o cdrom.o + obj-$(CONFIG_GDROM) += gdrom.o cdrom.o +--- sle11sp1-2010-03-22.orig/drivers/xen/blkfront/Makefile 2007-06-12 13:13:44.000000000 +0200 ++++ sle11sp1-2010-03-22/drivers/xen/blkfront/Makefile 2009-10-15 12:13:13.000000000 +0200 +@@ -1,5 +1,5 @@ + + obj-$(CONFIG_XEN_BLKDEV_FRONTEND) := xenblk.o + +-xenblk-objs := blkfront.o vbd.o ++xenblk-objs := blkfront.o vbd.o vcd.o + +--- sle11sp1-2010-03-22.orig/drivers/xen/blkfront/blkfront.c 2010-03-22 12:57:12.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/xen/blkfront/blkfront.c 2010-03-22 12:57:16.000000000 +0100 +@@ -395,6 +395,8 @@ static void connect(struct blkfront_info + add_disk(info->gd); + + info->is_ready = 1; ++ ++ register_vcd(info); + } + + /** +@@ -424,6 +426,8 @@ static void blkfront_closing(struct blkf + + xlvbd_sysfs_delif(info); + ++ unregister_vcd(info); ++ + xlvbd_del(info); + + out: +--- sle11sp1-2010-03-22.orig/drivers/xen/blkfront/block.h 2010-01-18 16:49:13.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/xen/blkfront/block.h 2010-01-18 17:06:20.000000000 +0100 +@@ -163,4 +163,8 @@ static inline void xlvbd_sysfs_delif(str + } + #endif + ++/* Virtual cdrom block-device */ ++extern void register_vcd(struct blkfront_info *info); ++extern void unregister_vcd(struct blkfront_info *info); ++ + #endif /* __XEN_DRIVERS_BLOCK_H__ */ +--- sle11sp1-2010-03-22.orig/drivers/xen/blkfront/vbd.c 2010-01-18 16:54:56.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/xen/blkfront/vbd.c 2010-01-18 17:06:22.000000000 +0100 +@@ -370,7 +370,8 @@ xlvbd_add(blkif_sector_t capacity, int v + goto out; + info->mi = mi; + +- if ((minor & ((1 << mi->type->partn_shift) - 1)) == 0) ++ if (!(vdisk_info & VDISK_CDROM) && ++ (minor & ((1 << mi->type->partn_shift) - 1)) == 0) + nr_minors = 1 << mi->type->partn_shift; + + err = xlbd_reserve_minors(mi, minor, nr_minors); +@@ -384,7 +385,7 @@ xlvbd_add(blkif_sector_t capacity, int v + + offset = mi->index * mi->type->disks_per_major + + (minor >> mi->type->partn_shift); +- if (nr_minors > 1) { ++ if (nr_minors > 1 || (vdisk_info & VDISK_CDROM)) { + if (offset < 26) { + sprintf(gd->disk_name, "%s%c", + mi->type->diskname, 'a' + offset ); +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/drivers/xen/blkfront/vcd.c 2010-02-09 17:17:54.000000000 +0100 +@@ -0,0 +1,509 @@ ++/******************************************************************************* ++ * vcd.c ++ * ++ * Implements CDROM cmd packet passing between frontend guest and backend driver. ++ * ++ * Copyright (c) 2008, Pat Campell plc@novell.com ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this source file (the "Software"), to deal in the Software without ++ * restriction, including without limitation the rights to use, copy, modify, ++ * merge, publish, distribute, sublicense, and/or sell copies of the Software, ++ * and to permit persons to whom the Software is furnished to do so, subject to ++ * the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS ++ * IN THE SOFTWARE. ++ */ ++ ++#define REVISION "$Revision: 1.0 $" ++ ++#include ++#include ++#include ++#include ++#include ++#include "block.h" ++ ++/* List of cdrom_device_info, can have as many as blkfront supports */ ++struct vcd_disk { ++ struct list_head vcd_entry; ++ struct cdrom_device_info vcd_cdrom_info; ++ spinlock_t vcd_cdrom_info_lock; ++}; ++static LIST_HEAD(vcd_disks); ++static DEFINE_SPINLOCK(vcd_disks_lock); ++ ++static struct vcd_disk *xencdrom_get_list_entry(struct gendisk *disk) ++{ ++ struct vcd_disk *ret_vcd = NULL; ++ struct vcd_disk *vcd; ++ ++ spin_lock(&vcd_disks_lock); ++ list_for_each_entry(vcd, &vcd_disks, vcd_entry) { ++ if (vcd->vcd_cdrom_info.disk == disk) { ++ spin_lock(&vcd->vcd_cdrom_info_lock); ++ ret_vcd = vcd; ++ break; ++ } ++ } ++ spin_unlock(&vcd_disks_lock); ++ return ret_vcd; ++} ++ ++static void submit_message(struct blkfront_info *info, void *sp) ++{ ++ struct request *req = NULL; ++ ++ req = blk_get_request(info->rq, READ, __GFP_WAIT); ++ if (blk_rq_map_kern(info->rq, req, sp, PAGE_SIZE, __GFP_WAIT)) ++ goto out; ++ ++ req->rq_disk = info->gd; ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18) ++ req->cmd_type = REQ_TYPE_BLOCK_PC; ++ req->cmd_flags |= REQ_NOMERGE; ++#else ++ req->flags |= REQ_BLOCK_PC; ++#endif ++ req->__sector = 0; ++ req->__data_len = PAGE_SIZE; ++ req->timeout = 60*HZ; ++ ++ blk_execute_rq(req->q, info->gd, req, 1); ++ ++out: ++ blk_put_request(req); ++} ++ ++static int submit_cdrom_cmd(struct blkfront_info *info, ++ struct packet_command *cgc) ++{ ++ int ret = 0; ++ struct page *page; ++ size_t size; ++ union xen_block_packet *sp; ++ struct xen_cdrom_packet *xcp; ++ struct vcd_generic_command *vgc; ++ ++ if (cgc->buffer && cgc->buflen > MAX_PACKET_DATA) { ++ printk(KERN_WARNING "%s() Packet buffer length is to large \n", __func__); ++ return -EIO; ++ } ++ ++ page = alloc_page(GFP_NOIO); ++ if (!page) { ++ printk(KERN_CRIT "%s() Unable to allocate page\n", __func__); ++ return -ENOMEM; ++ } ++ ++ size = PAGE_SIZE; ++ memset(page_address(page), 0, PAGE_SIZE); ++ sp = page_address(page); ++ xcp = &(sp->xcp); ++ xcp->type = XEN_TYPE_CDROM_PACKET; ++ xcp->payload_offset = PACKET_PAYLOAD_OFFSET; ++ ++ vgc = (struct vcd_generic_command *)((char *)sp + xcp->payload_offset); ++ memcpy(vgc->cmd, cgc->cmd, CDROM_PACKET_SIZE); ++ vgc->stat = cgc->stat; ++ vgc->data_direction = cgc->data_direction; ++ vgc->quiet = cgc->quiet; ++ vgc->timeout = cgc->timeout; ++ if (cgc->sense) { ++ vgc->sense_offset = PACKET_SENSE_OFFSET; ++ memcpy((char *)sp + vgc->sense_offset, cgc->sense, sizeof(struct request_sense)); ++ } ++ if (cgc->buffer) { ++ vgc->buffer_offset = PACKET_BUFFER_OFFSET; ++ memcpy((char *)sp + vgc->buffer_offset, cgc->buffer, cgc->buflen); ++ vgc->buflen = cgc->buflen; ++ } ++ ++ submit_message(info,sp); ++ ++ if (xcp->ret) ++ ret = xcp->err; ++ ++ if (cgc->sense) { ++ memcpy(cgc->sense, (char *)sp + PACKET_SENSE_OFFSET, sizeof(struct request_sense)); ++ } ++ if (cgc->buffer && cgc->buflen) { ++ memcpy(cgc->buffer, (char *)sp + PACKET_BUFFER_OFFSET, cgc->buflen); ++ } ++ ++ __free_page(page); ++ return ret; ++} ++ ++ ++static int xencdrom_open(struct cdrom_device_info *cdi, int purpose) ++{ ++ int ret = 0; ++ struct page *page; ++ struct blkfront_info *info; ++ union xen_block_packet *sp; ++ struct xen_cdrom_open *xco; ++ ++ info = cdi->disk->private_data; ++ ++ if (!info->xbdev) ++ return -ENODEV; ++ ++ if (strlen(info->xbdev->otherend) > MAX_PACKET_DATA) { ++ return -EIO; ++ } ++ ++ page = alloc_page(GFP_NOIO); ++ if (!page) { ++ printk(KERN_CRIT "%s() Unable to allocate page\n", __func__); ++ return -ENOMEM; ++ } ++ ++ memset(page_address(page), 0, PAGE_SIZE); ++ sp = page_address(page); ++ xco = &(sp->xco); ++ xco->type = XEN_TYPE_CDROM_OPEN; ++ xco->payload_offset = sizeof(struct xen_cdrom_open); ++ strcpy((char *)sp + xco->payload_offset, info->xbdev->otherend); ++ ++ submit_message(info,sp); ++ ++ if (xco->ret) { ++ ret = xco->err; ++ goto out; ++ } ++ ++ if (xco->media_present) ++ set_capacity(cdi->disk, xco->sectors); ++ ++out: ++ __free_page(page); ++ return ret; ++} ++ ++static void xencdrom_release(struct cdrom_device_info *cdi) ++{ ++} ++ ++static int xencdrom_media_changed(struct cdrom_device_info *cdi, int disc_nr) ++{ ++ int ret; ++ struct page *page; ++ struct blkfront_info *info; ++ union xen_block_packet *sp; ++ struct xen_cdrom_media_changed *xcmc; ++ ++ info = cdi->disk->private_data; ++ ++ page = alloc_page(GFP_NOIO); ++ if (!page) { ++ printk(KERN_CRIT "%s() Unable to allocate page\n", __func__); ++ return -ENOMEM; ++ } ++ ++ memset(page_address(page), 0, PAGE_SIZE); ++ sp = page_address(page); ++ xcmc = &(sp->xcmc); ++ xcmc->type = XEN_TYPE_CDROM_MEDIA_CHANGED; ++ submit_message(info,sp); ++ ret = xcmc->media_changed; ++ ++ __free_page(page); ++ ++ return ret; ++} ++ ++static int xencdrom_tray_move(struct cdrom_device_info *cdi, int position) ++{ ++ int ret; ++ struct packet_command cgc; ++ struct blkfront_info *info; ++ ++ info = cdi->disk->private_data; ++ init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE); ++ cgc.cmd[0] = GPCMD_START_STOP_UNIT; ++ if (position) ++ cgc.cmd[4] = 2; ++ else ++ cgc.cmd[4] = 3; ++ ret = submit_cdrom_cmd(info, &cgc); ++ return ret; ++} ++ ++static int xencdrom_lock_door(struct cdrom_device_info *cdi, int lock) ++{ ++ int ret = 0; ++ struct blkfront_info *info; ++ struct packet_command cgc; ++ ++ info = cdi->disk->private_data; ++ init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE); ++ cgc.cmd[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL; ++ cgc.cmd[4] = lock; ++ ret = submit_cdrom_cmd(info, &cgc); ++ return ret; ++} ++ ++static int xencdrom_packet(struct cdrom_device_info *cdi, ++ struct packet_command *cgc) ++{ ++ int ret = -EIO; ++ struct blkfront_info *info; ++ ++ info = cdi->disk->private_data; ++ ret = submit_cdrom_cmd(info, cgc); ++ cgc->stat = ret; ++ return ret; ++} ++ ++static int xencdrom_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, ++ void *arg) ++{ ++ return -EINVAL; ++} ++ ++/* Query backend to see if CDROM packets are supported */ ++static int xencdrom_supported(struct blkfront_info *info) ++{ ++ struct page *page; ++ union xen_block_packet *sp; ++ struct xen_cdrom_support *xcs; ++ ++ page = alloc_page(GFP_NOIO); ++ if (!page) { ++ printk(KERN_CRIT "%s() Unable to allocate page\n", __func__); ++ return -ENOMEM; ++ } ++ ++ memset(page_address(page), 0, PAGE_SIZE); ++ sp = page_address(page); ++ xcs = &(sp->xcs); ++ xcs->type = XEN_TYPE_CDROM_SUPPORT; ++ submit_message(info,sp); ++ return xcs->supported; ++} ++ ++static struct cdrom_device_ops xencdrom_dops = { ++ .open = xencdrom_open, ++ .release = xencdrom_release, ++ .media_changed = xencdrom_media_changed, ++ .tray_move = xencdrom_tray_move, ++ .lock_door = xencdrom_lock_door, ++ .generic_packet = xencdrom_packet, ++ .audio_ioctl = xencdrom_audio_ioctl, ++ .capability = (CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | \ ++ CDC_MEDIA_CHANGED | CDC_GENERIC_PACKET | CDC_DVD | \ ++ CDC_CD_R), ++ .n_minors = 1, ++}; ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ++static int xencdrom_block_open(struct inode *inode, struct file *file) ++{ ++ struct block_device *bd = inode->i_bdev; ++#else ++static int xencdrom_block_open(struct block_device *bd, fmode_t mode) ++{ ++#endif ++ struct blkfront_info *info = bd->bd_disk->private_data; ++ struct vcd_disk *vcd; ++ int ret = 0; ++ ++ if (!info->xbdev) ++ return -ENODEV; ++ ++ if ((vcd = xencdrom_get_list_entry(info->gd))) { ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ++ ret = cdrom_open(&vcd->vcd_cdrom_info, inode, file); ++#else ++ ret = cdrom_open(&vcd->vcd_cdrom_info, bd, mode); ++#endif ++ info->users = vcd->vcd_cdrom_info.use_count; ++ spin_unlock(&vcd->vcd_cdrom_info_lock); ++ } ++ return ret; ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ++static int xencdrom_block_release(struct inode *inode, struct file *file) ++{ ++ struct gendisk *gd = inode->i_bdev->bd_disk; ++#else ++static int xencdrom_block_release(struct gendisk *gd, fmode_t mode) ++{ ++#endif ++ struct blkfront_info *info = gd->private_data; ++ struct vcd_disk *vcd; ++ int ret = 0; ++ ++ if ((vcd = xencdrom_get_list_entry(info->gd))) { ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ++ ret = cdrom_release(&vcd->vcd_cdrom_info, file); ++#else ++ cdrom_release(&vcd->vcd_cdrom_info, mode); ++#endif ++ spin_unlock(&vcd->vcd_cdrom_info_lock); ++ if (vcd->vcd_cdrom_info.use_count == 0) { ++ info->users = 1; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ++ blkif_release(inode, file); ++#else ++ blkif_release(gd, mode); ++#endif ++ } ++ } ++ return ret; ++} ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ++static int xencdrom_block_ioctl(struct inode *inode, struct file *file, ++ unsigned cmd, unsigned long arg) ++{ ++ struct block_device *bd = inode->i_bdev; ++#else ++static int xencdrom_block_ioctl(struct block_device *bd, fmode_t mode, ++ unsigned cmd, unsigned long arg) ++{ ++#endif ++ struct blkfront_info *info = bd->bd_disk->private_data; ++ struct vcd_disk *vcd; ++ int ret = 0; ++ ++ if (!(vcd = xencdrom_get_list_entry(info->gd))) ++ goto out; ++ ++ switch (cmd) { ++ case 2285: /* SG_IO */ ++ ret = -ENOSYS; ++ break; ++ case CDROMEJECT: ++ ret = xencdrom_tray_move(&vcd->vcd_cdrom_info, 1); ++ break; ++ case CDROMCLOSETRAY: ++ ret = xencdrom_tray_move(&vcd->vcd_cdrom_info, 0); ++ break; ++ case CDROM_GET_CAPABILITY: ++ ret = vcd->vcd_cdrom_info.ops->capability & ~vcd->vcd_cdrom_info.mask; ++ break; ++ case CDROM_SET_OPTIONS: ++ ret = vcd->vcd_cdrom_info.options; ++ break; ++ case CDROM_SEND_PACKET: ++ ret = submit_cdrom_cmd(info, (struct packet_command *)arg); ++ break; ++ default: ++ /* Not supported, augment supported above if necessary */ ++ printk("%s():%d Unsupported IOCTL:%x \n", __func__, __LINE__, cmd); ++ ret = -ENOTTY; ++ break; ++ } ++ spin_unlock(&vcd->vcd_cdrom_info_lock); ++out: ++ return ret; ++} ++ ++/* Called as result of cdrom_open, vcd_cdrom_info_lock already held */ ++static int xencdrom_block_media_changed(struct gendisk *disk) ++{ ++ struct vcd_disk *vcd; ++ struct vcd_disk *ret_vcd = NULL; ++ int ret = 0; ++ ++ spin_lock(&vcd_disks_lock); ++ list_for_each_entry(vcd, &vcd_disks, vcd_entry) { ++ if (vcd->vcd_cdrom_info.disk == disk) { ++ ret_vcd = vcd; ++ break; ++ } ++ } ++ spin_unlock(&vcd_disks_lock); ++ if (ret_vcd) { ++ ret = cdrom_media_changed(&ret_vcd->vcd_cdrom_info); ++ } ++ return ret; ++} ++ ++static const struct block_device_operations xencdrom_bdops = ++{ ++ .owner = THIS_MODULE, ++ .open = xencdrom_block_open, ++ .release = xencdrom_block_release, ++ .ioctl = xencdrom_block_ioctl, ++ .media_changed = xencdrom_block_media_changed, ++}; ++ ++void register_vcd(struct blkfront_info *info) ++{ ++ struct gendisk *gd = info->gd; ++ struct vcd_disk *vcd; ++ ++ /* Make sure this is for a CD device */ ++ if (!(gd->flags & GENHD_FL_CD)) ++ goto out; ++ ++ /* Make sure we have backend support */ ++ if (!xencdrom_supported(info)) { ++ goto out; ++ } ++ ++ /* Create new vcd_disk and fill in cdrom_info */ ++ vcd = (struct vcd_disk *)kzalloc(sizeof(struct vcd_disk), GFP_KERNEL); ++ if (!vcd) { ++ printk(KERN_INFO "%s(): Unable to allocate vcd struct!\n", __func__); ++ goto out; ++ } ++ spin_lock_init(&vcd->vcd_cdrom_info_lock); ++ ++ vcd->vcd_cdrom_info.ops = &xencdrom_dops; ++ vcd->vcd_cdrom_info.speed = 4; ++ vcd->vcd_cdrom_info.capacity = 1; ++ vcd->vcd_cdrom_info.options = 0; ++ strcpy(vcd->vcd_cdrom_info.name, gd->disk_name); ++ vcd->vcd_cdrom_info.mask = (CDC_CD_RW | CDC_DVD_R | CDC_DVD_RAM | ++ CDC_SELECT_DISC | CDC_SELECT_SPEED | ++ CDC_MRW | CDC_MRW_W | CDC_RAM); ++ ++ if (register_cdrom(&(vcd->vcd_cdrom_info)) != 0) { ++ printk(KERN_WARNING "%s() Cannot register blkdev as a cdrom %d!\n", __func__, ++ gd->major); ++ goto err_out; ++ } ++ gd->fops = &xencdrom_bdops; ++ vcd->vcd_cdrom_info.disk = gd; ++ ++ spin_lock(&vcd_disks_lock); ++ list_add(&(vcd->vcd_entry), &vcd_disks); ++ spin_unlock(&vcd_disks_lock); ++out: ++ return; ++err_out: ++ kfree(vcd); ++} ++ ++void unregister_vcd(struct blkfront_info *info) { ++ struct gendisk *gd = info->gd; ++ struct vcd_disk *vcd; ++ ++ spin_lock(&vcd_disks_lock); ++ list_for_each_entry(vcd, &vcd_disks, vcd_entry) { ++ if (vcd->vcd_cdrom_info.disk == gd) { ++ spin_lock(&vcd->vcd_cdrom_info_lock); ++ unregister_cdrom(&vcd->vcd_cdrom_info); ++ list_del(&vcd->vcd_entry); ++ spin_unlock(&vcd->vcd_cdrom_info_lock); ++ kfree(vcd); ++ break; ++ } ++ } ++ spin_unlock(&vcd_disks_lock); ++} ++ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/include/xen/interface/io/cdromif.h 2009-10-15 12:13:13.000000000 +0200 +@@ -0,0 +1,120 @@ ++/****************************************************************************** ++ * cdromif.h ++ * ++ * Shared definitions between backend driver and Xen guest Virtual CDROM ++ * block device. ++ * ++ * Copyright (c) 2008, Pat Campell plc@novell.com ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this source file (the "Software"), to deal in the Software without ++ * restriction, including without limitation the rights to use, copy, modify, ++ * merge, publish, distribute, sublicense, and/or sell copies of the Software, ++ * and to permit persons to whom the Software is furnished to do so, subject to ++ * the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS ++ * IN THE SOFTWARE. ++ */ ++ ++#ifndef __XEN_PUBLIC_IO_CDROMIF_H__ ++#define __XEN_PUBLIC_IO_CDROMIF_H__ ++ ++/* ++ * Queries backend for CDROM support ++ */ ++#define XEN_TYPE_CDROM_SUPPORT _IO('c', 1) ++ ++struct xen_cdrom_support ++{ ++ uint32_t type; ++ int8_t ret; /* returned, 0 succeded, -1 error */ ++ int8_t err; /* returned, backend errno */ ++ int8_t supported; /* returned, 1 supported */ ++}; ++ ++/* ++ * Opens backend device, returns drive geometry or ++ * any encountered errors ++ */ ++#define XEN_TYPE_CDROM_OPEN _IO('c', 2) ++ ++struct xen_cdrom_open ++{ ++ uint32_t type; ++ int8_t ret; ++ int8_t err; ++ int8_t pad; ++ int8_t media_present; /* returned */ ++ uint32_t sectors; /* returned */ ++ uint32_t sector_size; /* returned */ ++ int32_t payload_offset; /* offset to backend node name payload */ ++}; ++ ++/* ++ * Queries backend for media changed status ++ */ ++#define XEN_TYPE_CDROM_MEDIA_CHANGED _IO('c', 3) ++ ++struct xen_cdrom_media_changed ++{ ++ uint32_t type; ++ int8_t ret; ++ int8_t err; ++ int8_t media_changed; /* returned */ ++}; ++ ++/* ++ * Sends vcd generic CDROM packet to backend, followed ++ * immediately by the vcd_generic_command payload ++ */ ++#define XEN_TYPE_CDROM_PACKET _IO('c', 4) ++ ++struct xen_cdrom_packet ++{ ++ uint32_t type; ++ int8_t ret; ++ int8_t err; ++ int8_t pad[2]; ++ int32_t payload_offset; /* offset to vcd_generic_command payload */ ++}; ++ ++/* CDROM_PACKET_COMMAND, payload for XEN_TYPE_CDROM_PACKET */ ++struct vcd_generic_command ++{ ++ uint8_t cmd[CDROM_PACKET_SIZE]; ++ uint8_t pad[4]; ++ uint32_t buffer_offset; ++ uint32_t buflen; ++ int32_t stat; ++ uint32_t sense_offset; ++ uint8_t data_direction; ++ uint8_t pad1[3]; ++ int32_t quiet; ++ int32_t timeout; ++}; ++ ++union xen_block_packet ++{ ++ uint32_t type; ++ struct xen_cdrom_support xcs; ++ struct xen_cdrom_open xco; ++ struct xen_cdrom_media_changed xcmc; ++ struct xen_cdrom_packet xcp; ++}; ++ ++#define PACKET_PAYLOAD_OFFSET (sizeof(struct xen_cdrom_packet)) ++#define PACKET_SENSE_OFFSET (PACKET_PAYLOAD_OFFSET + sizeof(struct vcd_generic_command)) ++#define PACKET_BUFFER_OFFSET (PACKET_SENSE_OFFSET + sizeof(struct request_sense)) ++#define MAX_PACKET_DATA (PAGE_SIZE - sizeof(struct xen_cdrom_packet) - \ ++ sizeof(struct vcd_generic_command) - sizeof(struct request_sense)) ++ ++#endif diff --git a/xen-blkif-protocol-fallback-hack b/xen-blkif-protocol-fallback-hack new file mode 100644 index 0000000..63a7e34 --- /dev/null +++ b/xen-blkif-protocol-fallback-hack @@ -0,0 +1,219 @@ +Subject: 32-on-64 blkif protocol negotiation fallback for old guests. +From: kraxel@suse.de +References: 244055 +Patch-mainline: never. + +See the comment below. Oh well. + +--- sle11sp1-2010-03-29.orig/drivers/xen/Kconfig 2010-03-26 08:39:39.000000000 +0100 ++++ sle11sp1-2010-03-29/drivers/xen/Kconfig 2010-03-29 09:12:44.000000000 +0200 +@@ -29,6 +29,9 @@ config XEN_PRIVCMD + def_bool y + depends on PROC_FS + ++config XEN_DOMCTL ++ tristate ++ + config XEN_XENBUS_DEV + def_bool y + depends on PROC_FS +@@ -48,6 +51,7 @@ config XEN_BLKDEV_BACKEND + tristate "Block-device backend driver" + depends on XEN_BACKEND + default XEN_BACKEND ++ select XEN_DOMCTL + help + The block-device backend driver allows the kernel to export its + block devices to other guests via a high-performance shared-memory +@@ -57,6 +61,7 @@ config XEN_BLKDEV_TAP + tristate "Block-device tap backend driver" + depends on XEN_BACKEND + default XEN_BACKEND ++ select XEN_DOMCTL + help + The block tap driver is an alternative to the block back driver + and allows VM block requests to be redirected to userspace through +--- sle11sp1-2010-03-29.orig/drivers/xen/blkback/xenbus.c 2010-03-22 12:53:24.000000000 +0100 ++++ sle11sp1-2010-03-29/drivers/xen/blkback/xenbus.c 2010-03-22 12:53:34.000000000 +0100 +@@ -21,6 +21,7 @@ + #include + #include + #include "common.h" ++#include "../core/domctl.h" + + #undef DPRINTK + #define DPRINTK(fmt, args...) \ +@@ -492,8 +493,10 @@ static int connect_ring(struct backend_i + be->blkif->blk_protocol = BLKIF_PROTOCOL_NATIVE; + err = xenbus_gather(XBT_NIL, dev->otherend, "protocol", + "%63s", protocol, NULL); +- if (err) +- strcpy(protocol, "unspecified, assuming native"); ++ if (err) { ++ strcpy(protocol, "unspecified"); ++ be->blkif->blk_protocol = xen_guest_blkif_protocol(be->blkif->domid); ++ } + else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_NATIVE)) + be->blkif->blk_protocol = BLKIF_PROTOCOL_NATIVE; + else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_X86_32)) +--- sle11sp1-2010-03-29.orig/drivers/xen/blktap/xenbus.c 2010-01-27 14:59:26.000000000 +0100 ++++ sle11sp1-2010-03-29/drivers/xen/blktap/xenbus.c 2010-01-27 15:00:09.000000000 +0100 +@@ -39,6 +39,7 @@ + #include + #include + #include "common.h" ++#include "../core/domctl.h" + + + struct backend_info +@@ -432,8 +433,10 @@ static int connect_ring(struct backend_i + be->blkif->blk_protocol = BLKIF_PROTOCOL_NATIVE; + err = xenbus_gather(XBT_NIL, dev->otherend, "protocol", + "%63s", protocol, NULL); +- if (err) +- strcpy(protocol, "unspecified, assuming native"); ++ if (err) { ++ strcpy(protocol, "unspecified"); ++ be->blkif->blk_protocol = xen_guest_blkif_protocol(be->blkif->domid); ++ } + else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_NATIVE)) + be->blkif->blk_protocol = BLKIF_PROTOCOL_NATIVE; + else if (0 == strcmp(protocol, XEN_IO_PROTO_ABI_X86_32)) +--- sle11sp1-2010-03-29.orig/drivers/xen/core/Makefile 2009-11-06 10:52:02.000000000 +0100 ++++ sle11sp1-2010-03-29/drivers/xen/core/Makefile 2010-01-04 16:17:00.000000000 +0100 +@@ -12,4 +12,7 @@ obj-$(CONFIG_XEN_SYSFS) += xen_sysfs.o + obj-$(CONFIG_XEN_SMPBOOT) += smpboot.o + obj-$(CONFIG_SMP) += spinlock.o + obj-$(CONFIG_KEXEC) += machine_kexec.o ++obj-$(CONFIG_XEN_DOMCTL) += domctl.o ++CFLAGS_domctl.o := -D__XEN_PUBLIC_XEN_H__ -D__XEN_PUBLIC_GRANT_TABLE_H__ ++CFLAGS_domctl.o += -D__XEN_TOOLS__ -imacros xen/interface/domctl.h + obj-$(CONFIG_XEN_XENCOMM) += xencomm.o +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-29/drivers/xen/core/domctl.c 2010-01-04 16:15:58.000000000 +0100 +@@ -0,0 +1,120 @@ ++/* ++ * !!! dirty hack alert !!! ++ * ++ * Problem: old guests kernels don't have a "protocol" node ++ * in the frontend xenstore directory, so mixing ++ * 32 and 64bit domains doesn't work. ++ * ++ * Upstream plans to solve this in the tools, by letting them ++ * create a protocol node. Which certainly makes sense. ++ * But it isn't trivial and isn't done yet. Too bad. ++ * ++ * So for the time being we use the get_address_size domctl ++ * hypercall for a pretty good guess. Not nice as the domctl ++ * hypercall isn't supposed to be used by the kernel. Because ++ * we don't want to have dependencies between dom0 kernel and ++ * xen kernel versions. Now we have one. Ouch. ++ */ ++#undef __XEN_PUBLIC_XEN_H__ ++#undef __XEN_PUBLIC_GRANT_TABLE_H__ ++#undef __XEN_TOOLS__ ++#include ++#include ++#include ++#include ++ ++#include "domctl.h" ++ ++/* stuff copied from xen/interface/domctl.h, which we can't ++ * include directly for the reasons outlined above .... */ ++ ++typedef struct xen_domctl_address_size { ++ uint32_t size; ++} xen_domctl_address_size_t; ++ ++typedef __attribute__((aligned(8))) uint64_t uint64_aligned_t; ++ ++union xen_domctl { ++ /* v4: sles10 sp1: xen 3.0.4 + 32-on-64 patches */ ++ struct { ++ uint32_t cmd; ++ uint32_t interface_version; ++ domid_t domain; ++ union { ++ /* left out lots of other struct xen_domctl_foobar */ ++ struct xen_domctl_address_size address_size; ++ uint64_t dummy_align; ++ uint8_t dummy_pad[128]; ++ }; ++ } v4; ++ ++ /* v5: upstream: xen 3.1, v6: upstream: xen 4.0 */ ++ struct { ++ uint32_t cmd; ++ uint32_t interface_version; ++ domid_t domain; ++ union { ++ struct xen_domctl_address_size address_size; ++ uint64_aligned_t dummy_align; ++ uint8_t dummy_pad[128]; ++ }; ++ } v5, v6; ++}; ++ ++/* The actual code comes here */ ++ ++static inline int hypervisor_domctl(void *domctl) ++{ ++ return _hypercall1(int, domctl, domctl); ++} ++ ++int xen_guest_address_size(int domid) ++{ ++ union xen_domctl domctl; ++ int low, ret; ++ ++#define guest_address_size(ver) do { \ ++ memset(&domctl, 0, sizeof(domctl)); \ ++ domctl.v##ver.cmd = XEN_DOMCTL_get_address_size; \ ++ domctl.v##ver.interface_version = low = ver; \ ++ domctl.v##ver.domain = domid; \ ++ ret = hypervisor_domctl(&domctl) ?: domctl.v##ver.address_size.size; \ ++ if (ret == 32 || ret == 64) { \ ++ printk("v" #ver " domctl worked ok: dom%d is %d-bit\n", \ ++ domid, ret); \ ++ return ret; \ ++ } \ ++} while (0) ++ ++ BUILD_BUG_ON(XEN_DOMCTL_INTERFACE_VERSION > 6); ++ guest_address_size(6); ++#if CONFIG_XEN_COMPAT < 0x040000 ++ guest_address_size(5); ++#endif ++#if CONFIG_XEN_COMPAT < 0x030100 ++ guest_address_size(4); ++#endif ++ ++ ret = BITS_PER_LONG; ++ printk("v%d...6 domctls failed, assuming dom%d is native: %d\n", ++ low, domid, ret); ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(xen_guest_address_size); ++ ++int xen_guest_blkif_protocol(int domid) ++{ ++ int address_size = xen_guest_address_size(domid); ++ ++ if (address_size == BITS_PER_LONG) ++ return BLKIF_PROTOCOL_NATIVE; ++ if (address_size == 32) ++ return BLKIF_PROTOCOL_X86_32; ++ if (address_size == 64) ++ return BLKIF_PROTOCOL_X86_64; ++ return BLKIF_PROTOCOL_NATIVE; ++} ++EXPORT_SYMBOL_GPL(xen_guest_blkif_protocol); ++ ++MODULE_LICENSE("GPL"); +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-29/drivers/xen/core/domctl.h 2008-09-15 15:10:39.000000000 +0200 +@@ -0,0 +1,2 @@ ++int xen_guest_address_size(int domid); ++int xen_guest_blkif_protocol(int domid); diff --git a/xen-blktap-write-barriers b/xen-blktap-write-barriers new file mode 100644 index 0000000..efcb2e5 --- /dev/null +++ b/xen-blktap-write-barriers @@ -0,0 +1,105 @@ +From: kwolf@suse.de +Subject: blktap: Write Barriers +Patch-mainline: obsolete + +--- sle11sp1-2010-01-27.orig/drivers/xen/blktap/blktap.c 2010-01-04 12:41:47.000000000 +0100 ++++ sle11sp1-2010-01-27/drivers/xen/blktap/blktap.c 2010-01-04 13:22:24.000000000 +0100 +@@ -1366,6 +1366,9 @@ static int do_block_io_op(blkif_t *blkif + dispatch_rw_block_io(blkif, &req, pending_req); + break; + ++ case BLKIF_OP_WRITE_BARRIER: ++ /* TODO Some counter? */ ++ /* Fall through */ + case BLKIF_OP_WRITE: + blkif->st_wr_req++; + dispatch_rw_block_io(blkif, &req, pending_req); +@@ -1397,7 +1400,7 @@ static void dispatch_rw_block_io(blkif_t + pending_req_t *pending_req) + { + extern void ll_rw_block(int rw, int nr, struct buffer_head * bhs[]); +- int op, operation = (req->operation == BLKIF_OP_WRITE) ? WRITE : READ; ++ int op, operation; + struct gnttab_map_grant_ref map[BLKIF_MAX_SEGMENTS_PER_REQUEST*2]; + unsigned int nseg; + int ret, i, nr_sects = 0; +@@ -1409,6 +1412,21 @@ static void dispatch_rw_block_io(blkif_t + struct mm_struct *mm; + struct vm_area_struct *vma = NULL; + ++ switch (req->operation) { ++ case BLKIF_OP_READ: ++ operation = READ; ++ break; ++ case BLKIF_OP_WRITE: ++ operation = WRITE; ++ break; ++ case BLKIF_OP_WRITE_BARRIER: ++ operation = WRITE_BARRIER; ++ break; ++ default: ++ operation = 0; /* make gcc happy */ ++ BUG(); ++ } ++ + if (blkif->dev_num < 0 || blkif->dev_num > MAX_TAP_DEV) + goto fail_response; + +@@ -1448,7 +1466,7 @@ static void dispatch_rw_block_io(blkif_t + + pending_req->blkif = blkif; + pending_req->id = req->id; +- pending_req->operation = operation; ++ pending_req->operation = req->operation; + pending_req->status = BLKIF_RSP_OKAY; + pending_req->nr_pages = nseg; + op = 0; +@@ -1465,7 +1483,7 @@ static void dispatch_rw_block_io(blkif_t + kvaddr = idx_to_kaddr(mmap_idx, pending_idx, i); + + flags = GNTMAP_host_map; +- if (operation == WRITE) ++ if (operation != READ) + flags |= GNTMAP_readonly; + gnttab_set_map_op(&map[op], kvaddr, flags, + req->seg[i].gref, blkif->domid); +@@ -1482,7 +1500,7 @@ static void dispatch_rw_block_io(blkif_t + + flags = GNTMAP_host_map | GNTMAP_application_map + | GNTMAP_contains_pte; +- if (operation == WRITE) ++ if (operation != READ) + flags |= GNTMAP_readonly; + gnttab_set_map_op(&map[op], ptep, flags, + req->seg[i].gref, blkif->domid); +--- sle11sp1-2010-01-27.orig/drivers/xen/blktap/xenbus.c 2010-01-27 15:00:09.000000000 +0100 ++++ sle11sp1-2010-01-27/drivers/xen/blktap/xenbus.c 2010-01-27 15:00:31.000000000 +0100 +@@ -401,7 +401,28 @@ static void connect(struct backend_info + int err; + + struct xenbus_device *dev = be->dev; ++ struct xenbus_transaction xbt; + ++ /* Write feature-barrier to xenstore */ ++again: ++ err = xenbus_transaction_start(&xbt); ++ if (err) { ++ xenbus_dev_fatal(dev, err, "starting transaction"); ++ return; ++ } ++ ++ err = xenbus_printf(xbt, dev->nodename, "feature-barrier", "1"); ++ if (err) { ++ xenbus_dev_fatal(dev, err, "writing feature-barrier"); ++ xenbus_transaction_end(xbt, 1); ++ return; ++ } ++ ++ err = xenbus_transaction_end(xbt, 0); ++ if (err == -EAGAIN) ++ goto again; ++ ++ /* Switch state */ + err = xenbus_switch_state(dev, XenbusStateConnected); + if (err) + xenbus_dev_fatal(dev, err, "switching to Connected state", diff --git a/xen-configurable-guest-devices b/xen-configurable-guest-devices new file mode 100644 index 0000000..c9edb82 --- /dev/null +++ b/xen-configurable-guest-devices @@ -0,0 +1,74 @@ +From: jbeulich@novell.com +Subject: allow number of guest devices to be configurable +Patch-mainline: obsolete + +... and derive NR_DYNIRQS from this (rather than having a hard-coded +value). +Similarly, allow the number of simultaneous transmits in netback to be +configurable. + +--- sle11sp1-2010-03-29.orig/arch/x86/include/mach-xen/asm/irq_vectors.h 2009-11-06 10:52:09.000000000 +0100 ++++ sle11sp1-2010-03-29/arch/x86/include/mach-xen/asm/irq_vectors.h 2009-12-22 13:21:47.000000000 +0100 +@@ -89,7 +89,7 @@ extern int nr_pirqs; + #endif + + #define DYNIRQ_BASE (PIRQ_BASE + nr_pirqs) +-#define NR_DYNIRQS 256 ++#define NR_DYNIRQS (64 + CONFIG_XEN_NR_GUEST_DEVICES) + + #define NR_IRQS (NR_PIRQS + NR_DYNIRQS) + +--- sle11sp1-2010-03-29.orig/drivers/xen/Kconfig 2010-03-29 09:13:07.000000000 +0200 ++++ sle11sp1-2010-03-29/drivers/xen/Kconfig 2010-03-29 09:13:14.000000000 +0200 +@@ -97,6 +97,15 @@ config XEN_NETDEV_BACKEND + network devices to other guests via a high-performance shared-memory + interface. + ++config XEN_NETDEV_TX_SHIFT ++ int "Maximum simultaneous transmit requests (as a power of 2)" ++ depends on XEN_NETDEV_BACKEND ++ range 5 16 ++ default 8 ++ help ++ The maximum number transmits the driver can hold pending, expressed ++ as the exponent of a power of 2. ++ + config XEN_NETDEV_PIPELINED_TRANSMITTER + bool "Pipelined transmitter (DANGEROUS)" + depends on XEN_NETDEV_BACKEND +@@ -308,6 +317,16 @@ config XEN_SYSFS + help + Xen hypervisor attributes will show up under /sys/hypervisor/. + ++config XEN_NR_GUEST_DEVICES ++ int "Number of guest devices" ++ range 0 4032 if 64BIT ++ range 0 960 ++ default 256 if XEN_BACKEND ++ default 16 ++ help ++ Specify the total number of virtual devices (i.e. both frontend ++ and backend) that you want the kernel to be able to service. ++ + choice + prompt "Xen version compatibility" + default XEN_COMPAT_030002_AND_LATER +--- sle11sp1-2010-03-29.orig/drivers/xen/netback/netback.c 2010-01-04 13:31:26.000000000 +0100 ++++ sle11sp1-2010-03-29/drivers/xen/netback/netback.c 2010-01-04 13:31:38.000000000 +0100 +@@ -71,7 +71,7 @@ static DECLARE_TASKLET(net_rx_tasklet, n + static struct timer_list net_timer; + static struct timer_list netbk_tx_pending_timer; + +-#define MAX_PENDING_REQS 256 ++#define MAX_PENDING_REQS (1U << CONFIG_XEN_NETDEV_TX_SHIFT) + + static struct sk_buff_head rx_queue; + +@@ -1265,6 +1265,7 @@ static void net_tx_action(unsigned long + net_tx_action_dealloc(); + + mop = tx_map_ops; ++ BUILD_BUG_ON(MAX_SKB_FRAGS >= MAX_PENDING_REQS); + while (((NR_PENDING_REQS + MAX_SKB_FRAGS) < MAX_PENDING_REQS) && + !list_empty(&net_schedule_list)) { + /* Get a netif from the list with work to do. */ diff --git a/xen-cpufreq-report b/xen-cpufreq-report new file mode 100644 index 0000000..2e3ae1b --- /dev/null +++ b/xen-cpufreq-report @@ -0,0 +1,57 @@ +From: jbeulich@novell.com +Subject: make /proc/cpuinfo track CPU speed +Patch-mainline: obsolete + +--- sle11sp1-2010-03-22.orig/arch/x86/kernel/acpi/processor_extcntl_xen.c 2010-03-22 12:00:53.000000000 +0100 ++++ sle11sp1-2010-03-22/arch/x86/kernel/acpi/processor_extcntl_xen.c 2010-03-22 12:57:38.000000000 +0100 +@@ -206,3 +206,14 @@ void arch_acpi_processor_init_extcntl(co + *ops = &xen_extcntl_ops; + } + EXPORT_SYMBOL(arch_acpi_processor_init_extcntl); ++ ++unsigned int cpufreq_quick_get(unsigned int cpu) ++{ ++ xen_platform_op_t op = { ++ .cmd = XENPF_get_cpu_freq, ++ .interface_version = XENPF_INTERFACE_VERSION, ++ .u.get_cpu_freq.vcpu = cpu ++ }; ++ ++ return HYPERVISOR_platform_op(&op) == 0 ? op.u.get_cpu_freq.freq : 0; ++} +--- sle11sp1-2010-03-22.orig/include/linux/cpufreq.h 2010-03-22 12:07:53.000000000 +0100 ++++ sle11sp1-2010-03-22/include/linux/cpufreq.h 2009-11-06 11:09:27.000000000 +0100 +@@ -302,7 +302,7 @@ static inline unsigned int cpufreq_get(u + #endif + + /* query the last known CPU freq (in kHz). If zero, cpufreq couldn't detect it */ +-#ifdef CONFIG_CPU_FREQ ++#if defined(CONFIG_CPU_FREQ) || defined(CONFIG_PROCESSOR_EXTERNAL_CONTROL) + unsigned int cpufreq_quick_get(unsigned int cpu); + #else + static inline unsigned int cpufreq_quick_get(unsigned int cpu) +--- sle11sp1-2010-03-22.orig/include/xen/interface/platform.h 2010-01-04 11:56:34.000000000 +0100 ++++ sle11sp1-2010-03-22/include/xen/interface/platform.h 2010-01-04 13:31:04.000000000 +0100 +@@ -355,6 +355,14 @@ struct xenpf_mem_hotadd + uint32_t flags; + }; + ++#define XENPF_get_cpu_freq ('N' << 24) ++struct xenpf_get_cpu_freq { ++ /* IN variables */ ++ uint32_t vcpu; ++ /* OUT variables */ ++ uint32_t freq; /* in kHz */ ++}; ++ + struct xen_platform_op { + uint32_t cmd; + uint32_t interface_version; /* XENPF_INTERFACE_VERSION */ +@@ -374,6 +382,7 @@ struct xen_platform_op { + struct xenpf_cpu_ol cpu_ol; + struct xenpf_cpu_hotadd cpu_add; + struct xenpf_mem_hotadd mem_add; ++ struct xenpf_get_cpu_freq get_cpu_freq; + uint8_t pad[128]; + } u; + }; diff --git a/xen-dcdbas b/xen-dcdbas new file mode 100644 index 0000000..de6ecb8 --- /dev/null +++ b/xen-dcdbas @@ -0,0 +1,280 @@ +From: jbeulich@novell.com +Subject: force proper address translation in DCDBAS +Patch-mainline: n/a + +The only caveat is that this doesn't work when Dom0 has its vCPU-s pinned. + +--- head-2010-01-04.orig/drivers/firmware/Kconfig 2009-11-06 11:10:32.000000000 +0100 ++++ head-2010-01-04/drivers/firmware/Kconfig 2009-10-21 12:05:13.000000000 +0200 +@@ -90,6 +90,7 @@ config DELL_RBU + config DCDBAS + tristate "Dell Systems Management Base Driver" + depends on X86 ++ select XEN_DOMCTL if XEN + help + The Dell Systems Management Base Driver provides a sysfs interface + for systems management software to perform System Management +--- head-2010-01-04.orig/drivers/firmware/dcdbas.c 2010-01-04 16:15:10.000000000 +0100 ++++ head-2010-01-04/drivers/firmware/dcdbas.c 2009-10-21 14:18:16.000000000 +0200 +@@ -36,6 +36,10 @@ + #include + #include + ++#ifdef CONFIG_XEN ++#include "../xen/core/domctl.h" ++#endif ++ + #include "dcdbas.h" + + #define DRIVER_NAME "dcdbas" +@@ -106,7 +110,7 @@ static int smi_data_buf_realloc(unsigned + /* set up new buffer for use */ + smi_data_buf = buf; + smi_data_buf_handle = handle; +- smi_data_buf_phys_addr = (u32) virt_to_phys(buf); ++ smi_data_buf_phys_addr = (u32) handle; + smi_data_buf_size = size; + + dev_dbg(&dcdbas_pdev->dev, "%s: phys: %x size: %lu\n", +@@ -244,7 +248,9 @@ static ssize_t host_control_on_shutdown_ + */ + int dcdbas_smi_request(struct smi_cmd *smi_cmd) + { ++#ifndef CONFIG_XEN + cpumask_var_t old_mask; ++#endif + int ret = 0; + + if (smi_cmd->magic != SMI_CMD_MAGIC) { +@@ -254,6 +260,7 @@ int dcdbas_smi_request(struct smi_cmd *s + } + + /* SMI requires CPU 0 */ ++#ifndef CONFIG_XEN + if (!alloc_cpumask_var(&old_mask, GFP_KERNEL)) + return -ENOMEM; + +@@ -265,6 +272,14 @@ int dcdbas_smi_request(struct smi_cmd *s + ret = -EBUSY; + goto out; + } ++#else ++ ret = xen_set_physical_cpu_affinity(0); ++ if (ret) { ++ dev_dbg(&dcdbas_pdev->dev, "%s: failed (%d) to get CPU 0\n", ++ __func__, ret); ++ return ret; ++ } ++#endif + + /* generate SMI */ + asm volatile ( +@@ -277,9 +292,13 @@ int dcdbas_smi_request(struct smi_cmd *s + : "memory" + ); + ++#ifndef CONFIG_XEN + out: + set_cpus_allowed_ptr(current, old_mask); + free_cpumask_var(old_mask); ++#else ++ xen_set_physical_cpu_affinity(-1); ++#endif + return ret; + } + +@@ -319,7 +338,7 @@ static ssize_t smi_request_store(struct + break; + case 1: + /* Calling Interface SMI */ +- smi_cmd->ebx = (u32) virt_to_phys(smi_cmd->command_buffer); ++ smi_cmd->ebx = (u32) virt_to_bus(smi_cmd->command_buffer); + ret = dcdbas_smi_request(smi_cmd); + if (!ret) + ret = count; +@@ -600,6 +619,11 @@ static int __init dcdbas_init(void) + { + int error; + ++#ifdef CONFIG_XEN ++ if (!is_initial_xendomain()) ++ return -ENODEV; ++#endif ++ + error = platform_driver_register(&dcdbas_driver); + if (error) + return error; +--- head-2010-01-04.orig/drivers/xen/core/domctl.c 2010-01-04 16:15:58.000000000 +0100 ++++ head-2010-01-04/drivers/xen/core/domctl.c 2010-01-04 16:17:59.000000000 +0100 +@@ -20,6 +20,8 @@ + #undef __XEN_TOOLS__ + #include + #include ++#include ++#include + #include + #include + +@@ -34,6 +36,29 @@ typedef struct xen_domctl_address_size { + + typedef __attribute__((aligned(8))) uint64_t uint64_aligned_t; + ++struct xenctl_cpumap_v4 { ++ XEN_GUEST_HANDLE(uint8) bitmap; ++ uint32_t nr_cpus; ++}; ++ ++struct xenctl_cpumap_v5 { ++ union { ++ XEN_GUEST_HANDLE(uint8) bitmap; ++ uint64_aligned_t _align; ++ }; ++ uint32_t nr_cpus; ++}; ++ ++struct xen_domctl_vcpuaffinity_v4 { ++ uint32_t vcpu; ++ struct xenctl_cpumap_v4 cpumap; ++}; ++ ++struct xen_domctl_vcpuaffinity_v5 { ++ uint32_t vcpu; ++ struct xenctl_cpumap_v5 cpumap; ++}; ++ + union xen_domctl { + /* v4: sles10 sp1: xen 3.0.4 + 32-on-64 patches */ + struct { +@@ -43,6 +68,7 @@ union xen_domctl { + union { + /* left out lots of other struct xen_domctl_foobar */ + struct xen_domctl_address_size address_size; ++ struct xen_domctl_vcpuaffinity_v4 vcpu_affinity; + uint64_t dummy_align; + uint8_t dummy_pad[128]; + }; +@@ -55,6 +81,7 @@ union xen_domctl { + domid_t domain; + union { + struct xen_domctl_address_size address_size; ++ struct xen_domctl_vcpuaffinity_v5 vcpu_affinity; + uint64_aligned_t dummy_align; + uint8_t dummy_pad[128]; + }; +@@ -117,4 +144,110 @@ int xen_guest_blkif_protocol(int domid) + } + EXPORT_SYMBOL_GPL(xen_guest_blkif_protocol); + ++#ifdef CONFIG_X86 ++ ++#define vcpuaffinity(what, ver) ({ \ ++ memset(&domctl, 0, sizeof(domctl)); \ ++ domctl.v##ver.cmd = XEN_DOMCTL_##what##vcpuaffinity; \ ++ domctl.v##ver.interface_version = ver; \ ++ /* domctl.v##ver.domain = 0; */ \ ++ domctl.v##ver.vcpu_affinity.vcpu = smp_processor_id(); \ ++ domctl.v##ver.vcpu_affinity.cpumap.nr_cpus = nr; \ ++ set_xen_guest_handle(domctl.v##ver.vcpu_affinity.cpumap.bitmap, \ ++ mask); \ ++ hypervisor_domctl(&domctl); \ ++}) ++ ++static inline int get_vcpuaffinity(unsigned int nr, void *mask) ++{ ++ union xen_domctl domctl; ++ int rc; ++ ++ BUILD_BUG_ON(XEN_DOMCTL_INTERFACE_VERSION > 6); ++ rc = vcpuaffinity(get, 6); ++#if CONFIG_XEN_COMPAT < 0x040000 ++ if (rc) ++ rc = vcpuaffinity(get, 5); ++#endif ++#if CONFIG_XEN_COMPAT < 0x030100 ++ if (rc) ++ rc = vcpuaffinity(get, 4); ++#endif ++ return rc; ++} ++ ++static inline int set_vcpuaffinity(unsigned int nr, void *mask) ++{ ++ union xen_domctl domctl; ++ int rc; ++ ++ BUILD_BUG_ON(XEN_DOMCTL_INTERFACE_VERSION > 6); ++ rc = vcpuaffinity(set, 6); ++#if CONFIG_XEN_COMPAT < 0x040000 ++ if (rc) ++ rc = vcpuaffinity(set, 5); ++#endif ++#if CONFIG_XEN_COMPAT < 0x030100 ++ if (rc) ++ rc = vcpuaffinity(set, 4); ++#endif ++ return rc; ++} ++ ++static DEFINE_PER_CPU(void *, saved_pcpu_affinity); ++ ++#define BITS_PER_PAGE (PAGE_SIZE * BITS_PER_LONG / sizeof(long)) ++ ++int xen_set_physical_cpu_affinity(int pcpu) ++{ ++ int rc; ++ ++ if (!is_initial_xendomain()) ++ return -EPERM; ++ ++ if (pcpu >= 0) { ++ void *oldmap; ++ ++ if (pcpu > BITS_PER_PAGE) ++ return -ERANGE; ++ ++ if (percpu_read(saved_pcpu_affinity)) ++ return -EBUSY; ++ ++ oldmap = (void *)get_zeroed_page(GFP_KERNEL); ++ if (!oldmap) ++ return -ENOMEM; ++ ++ rc = get_vcpuaffinity(BITS_PER_PAGE, oldmap); ++ if (!rc) { ++ void *newmap = kzalloc(BITS_TO_LONGS(pcpu + 1) ++ * sizeof(long), GFP_KERNEL); ++ ++ if (newmap) { ++ __set_bit(pcpu, newmap); ++ rc = set_vcpuaffinity(pcpu + 1, newmap); ++ kfree(newmap); ++ } else ++ rc = -ENOMEM; ++ } ++ ++ if (!rc) ++ percpu_write(saved_pcpu_affinity, oldmap); ++ else ++ free_page((unsigned long)oldmap); ++ } else { ++ if (!percpu_read(saved_pcpu_affinity)) ++ return 0; ++ rc = set_vcpuaffinity(BITS_PER_PAGE, ++ percpu_read(saved_pcpu_affinity)); ++ free_page((unsigned long)percpu_read(saved_pcpu_affinity)); ++ percpu_write(saved_pcpu_affinity, NULL); ++ } ++ ++ return rc; ++} ++EXPORT_SYMBOL_GPL(xen_set_physical_cpu_affinity); ++ ++#endif /* CONFIG_X86 */ ++ + MODULE_LICENSE("GPL"); +--- head-2010-01-04.orig/drivers/xen/core/domctl.h 2008-09-15 15:10:39.000000000 +0200 ++++ head-2010-01-04/drivers/xen/core/domctl.h 2009-10-21 13:24:42.000000000 +0200 +@@ -1,2 +1,3 @@ + int xen_guest_address_size(int domid); + int xen_guest_blkif_protocol(int domid); ++int xen_set_physical_cpu_affinity(int pcpu); diff --git a/xen-floppy b/xen-floppy new file mode 100644 index 0000000..f5a869b --- /dev/null +++ b/xen-floppy @@ -0,0 +1,28 @@ +From: jbeulich@novell.com +Subject: Xen: improve floppy behavior +Patch-mainline: n/a +References: bnc#584216 + +Timing is significantly different from native both because Xen traps +I/O port accesses and using DMA not being possible (without intrusive +changes). Due to the overhead of trapped port accesses, I/O is already +slow enough (and Xen doesn't run on very old hardware anyway), so the +situation can easily be improved by not enforcing REALLY_SLOW_IO. + +This doesn't completely address the issue - Xen just cannot guarantee +scheduling of a particular vCPU with a maximum latency of about 80us +(needed for the default FIFO threshold value of 10). The only complete +solution would require making ISA DMA usable on Xen. + +--- sle11sp1-2010-03-01.orig/drivers/block/floppy.c 2009-12-03 04:51:21.000000000 +0100 ++++ sle11sp1-2010-03-01/drivers/block/floppy.c 2010-03-05 09:16:48.000000000 +0100 +@@ -147,7 +147,9 @@ + #define FLOPPY_SANITY_CHECK + #undef FLOPPY_SILENT_DCL_CLEAR + ++#ifndef CONFIG_XEN + #define REALLY_SLOW_IO ++#endif + + #define DEBUGT 2 + #define DCL_DEBUG /* debug disk change line */ diff --git a/xen-ipi-per-cpu-irq b/xen-ipi-per-cpu-irq new file mode 100644 index 0000000..94f77b0 --- /dev/null +++ b/xen-ipi-per-cpu-irq @@ -0,0 +1,791 @@ +From: jbeulich@novell.com +Subject: fold IPIs onto a single IRQ each +Patch-mainline: obsolete + +--- sle11sp1-2010-03-29.orig/arch/x86/kernel/apic/ipi-xen.c 2009-11-06 10:52:02.000000000 +0100 ++++ sle11sp1-2010-03-29/arch/x86/kernel/apic/ipi-xen.c 2009-11-06 11:10:20.000000000 +0100 +@@ -21,31 +21,22 @@ + + #include + +-DECLARE_PER_CPU(int, ipi_to_irq[NR_IPIS]); +- +-static inline void __send_IPI_one(unsigned int cpu, int vector) +-{ +- int irq = per_cpu(ipi_to_irq, cpu)[vector]; +- BUG_ON(irq < 0); +- notify_remote_via_irq(irq); +-} +- + static void __send_IPI_shortcut(unsigned int shortcut, int vector) + { + unsigned int cpu; + + switch (shortcut) { + case APIC_DEST_SELF: +- __send_IPI_one(smp_processor_id(), vector); ++ notify_remote_via_ipi(vector, smp_processor_id()); + break; + case APIC_DEST_ALLBUT: + for_each_online_cpu(cpu) + if (cpu != smp_processor_id()) +- __send_IPI_one(cpu, vector); ++ notify_remote_via_ipi(vector, cpu); + break; + case APIC_DEST_ALLINC: + for_each_online_cpu(cpu) +- __send_IPI_one(cpu, vector); ++ notify_remote_via_ipi(vector, cpu); + break; + default: + printk("XXXXXX __send_IPI_shortcut %08x vector %d\n", shortcut, +@@ -63,7 +54,7 @@ void xen_send_IPI_mask_allbutself(const + WARN_ON(!cpumask_subset(cpumask, cpu_online_mask)); + for_each_cpu_and(cpu, cpumask, cpu_online_mask) + if (cpu != smp_processor_id()) +- __send_IPI_one(cpu, vector); ++ notify_remote_via_ipi(vector, cpu); + local_irq_restore(flags); + } + +@@ -75,7 +66,7 @@ void xen_send_IPI_mask(const struct cpum + local_irq_save(flags); + WARN_ON(!cpumask_subset(cpumask, cpu_online_mask)); + for_each_cpu_and(cpu, cpumask, cpu_online_mask) +- __send_IPI_one(cpu, vector); ++ notify_remote_via_ipi(vector, cpu); + local_irq_restore(flags); + } + +--- sle11sp1-2010-03-29.orig/arch/x86/kernel/irq-xen.c 2010-01-07 11:22:00.000000000 +0100 ++++ sle11sp1-2010-03-29/arch/x86/kernel/irq-xen.c 2010-01-07 11:22:50.000000000 +0100 +@@ -312,6 +312,7 @@ void fixup_irqs(void) + + affinity = desc->affinity; + if (!irq_has_action(irq) || ++ (desc->status & IRQ_PER_CPU) || + cpumask_equal(affinity, cpu_online_mask)) { + spin_unlock(&desc->lock); + continue; +--- sle11sp1-2010-03-29.orig/drivers/xen/Kconfig 2010-03-29 09:12:59.000000000 +0200 ++++ sle11sp1-2010-03-29/drivers/xen/Kconfig 2010-03-29 09:13:07.000000000 +0200 +@@ -4,6 +4,7 @@ + + config XEN + bool ++ select IRQ_PER_CPU if SMP + + if XEN + config XEN_INTERFACE_VERSION +@@ -350,6 +351,9 @@ endmenu + config HAVE_IRQ_IGNORE_UNHANDLED + def_bool y + ++config IRQ_PER_CPU ++ bool ++ + config NO_IDLE_HZ + def_bool y + +--- sle11sp1-2010-03-29.orig/drivers/xen/core/evtchn.c 2010-02-09 17:18:45.000000000 +0100 ++++ sle11sp1-2010-03-29/drivers/xen/core/evtchn.c 2010-02-09 17:18:51.000000000 +0100 +@@ -58,6 +58,22 @@ static DEFINE_SPINLOCK(irq_mapping_updat + static int evtchn_to_irq[NR_EVENT_CHANNELS] = { + [0 ... NR_EVENT_CHANNELS-1] = -1 }; + ++/* IRQ <-> IPI mapping. */ ++#ifndef NR_IPIS ++#define NR_IPIS 1 ++#endif ++#if defined(CONFIG_SMP) && defined(CONFIG_X86) ++static int ipi_to_irq[NR_IPIS] __read_mostly = {[0 ... NR_IPIS-1] = -1}; ++static DEFINE_PER_CPU(int[NR_IPIS], ipi_to_evtchn); ++#else ++#define PER_CPU_IPI_IRQ ++#endif ++#if !defined(CONFIG_SMP) || !defined(PER_CPU_IPI_IRQ) ++#define BUG_IF_IPI(irq) BUG_ON(type_from_irq(irq) == IRQT_IPI) ++#else ++#define BUG_IF_IPI(irq) ((void)(irq)) ++#endif ++ + /* Binding types. */ + enum { + IRQT_UNBOUND, +@@ -116,12 +132,14 @@ static inline u32 mk_irq_info(u32 type, + * Accessors for packed IRQ information. + */ + ++#ifdef PER_CPU_IPI_IRQ + static inline unsigned int evtchn_from_irq(int irq) + { + const struct irq_cfg *cfg = irq_cfg(irq); + + return cfg ? cfg->info & ((1U << _EVTCHN_BITS) - 1) : 0; + } ++#endif + + static inline unsigned int index_from_irq(int irq) + { +@@ -138,14 +156,32 @@ static inline unsigned int type_from_irq + return cfg ? cfg->info >> (32 - _IRQT_BITS) : IRQT_UNBOUND; + } + ++#ifndef PER_CPU_IPI_IRQ ++static inline unsigned int evtchn_from_per_cpu_irq(unsigned int irq, ++ unsigned int cpu) ++{ ++ BUG_ON(type_from_irq(irq) != IRQT_IPI); ++ return per_cpu(ipi_to_evtchn, cpu)[index_from_irq(irq)]; ++} ++ ++static inline unsigned int evtchn_from_irq(unsigned int irq) ++{ ++ if (type_from_irq(irq) != IRQT_IPI) { ++ const struct irq_cfg *cfg = irq_cfg(irq); ++ ++ return cfg ? cfg->info & ((1U << _EVTCHN_BITS) - 1) : 0; ++ } ++ return evtchn_from_per_cpu_irq(irq, smp_processor_id()); ++} ++#endif ++ + /* IRQ <-> VIRQ mapping. */ + DEFINE_PER_CPU(int[NR_VIRQS], virq_to_irq) = {[0 ... NR_VIRQS-1] = -1}; + ++#if defined(CONFIG_SMP) && defined(PER_CPU_IPI_IRQ) + /* IRQ <-> IPI mapping. */ +-#ifndef NR_IPIS +-#define NR_IPIS 1 +-#endif + DEFINE_PER_CPU(int[NR_IPIS], ipi_to_irq) = {[0 ... NR_IPIS-1] = -1}; ++#endif + + #ifdef CONFIG_SMP + +@@ -169,8 +205,14 @@ static void bind_evtchn_to_cpu(unsigned + + BUG_ON(!test_bit(chn, s->evtchn_mask)); + +- if (irq != -1) +- cpumask_copy(irq_to_desc(irq)->affinity, cpumask_of(cpu)); ++ if (irq != -1) { ++ struct irq_desc *desc = irq_to_desc(irq); ++ ++ if (!(desc->status & IRQ_PER_CPU)) ++ cpumask_copy(desc->affinity, cpumask_of(cpu)); ++ else ++ cpumask_set_cpu(cpu, desc->affinity); ++ } + + clear_bit(chn, per_cpu(cpu_evtchn_mask, cpu_evtchn[chn])); + set_bit(chn, per_cpu(cpu_evtchn_mask, cpu)); +@@ -344,7 +386,7 @@ asmlinkage void __irq_entry evtchn_do_up + + static struct irq_chip dynirq_chip; + +-static int find_unbound_irq(unsigned int cpu) ++static int find_unbound_irq(unsigned int cpu, bool percpu) + { + static int warned; + int irq; +@@ -354,10 +396,19 @@ static int find_unbound_irq(unsigned int + struct irq_cfg *cfg = desc->chip_data; + + if (!cfg->bindcount) { ++ irq_flow_handler_t handle; ++ const char *name; ++ + desc->status |= IRQ_NOPROBE; ++ if (!percpu) { ++ handle = handle_level_irq; ++ name = "level"; ++ } else { ++ handle = handle_percpu_irq; ++ name = "percpu"; ++ } + set_irq_chip_and_handler_name(irq, &dynirq_chip, +- handle_level_irq, +- "level"); ++ handle, name); + return irq; + } + } +@@ -378,7 +429,7 @@ static int bind_caller_port_to_irq(unsig + spin_lock(&irq_mapping_update_lock); + + if ((irq = evtchn_to_irq[caller_port]) == -1) { +- if ((irq = find_unbound_irq(smp_processor_id())) < 0) ++ if ((irq = find_unbound_irq(smp_processor_id(), false)) < 0) + goto out; + + evtchn_to_irq[caller_port] = irq; +@@ -401,7 +452,7 @@ static int bind_local_port_to_irq(unsign + + BUG_ON(evtchn_to_irq[local_port] != -1); + +- if ((irq = find_unbound_irq(smp_processor_id())) < 0) { ++ if ((irq = find_unbound_irq(smp_processor_id(), false)) < 0) { + struct evtchn_close close = { .port = local_port }; + if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close)) + BUG(); +@@ -454,7 +505,7 @@ static int bind_virq_to_irq(unsigned int + spin_lock(&irq_mapping_update_lock); + + if ((irq = per_cpu(virq_to_irq, cpu)[virq]) == -1) { +- if ((irq = find_unbound_irq(cpu)) < 0) ++ if ((irq = find_unbound_irq(cpu, false)) < 0) + goto out; + + bind_virq.virq = virq; +@@ -479,6 +530,7 @@ static int bind_virq_to_irq(unsigned int + return irq; + } + ++#if defined(CONFIG_SMP) && defined(PER_CPU_IPI_IRQ) + static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu) + { + struct evtchn_bind_ipi bind_ipi; +@@ -487,7 +539,7 @@ static int bind_ipi_to_irq(unsigned int + spin_lock(&irq_mapping_update_lock); + + if ((irq = per_cpu(ipi_to_irq, cpu)[ipi]) == -1) { +- if ((irq = find_unbound_irq(cpu)) < 0) ++ if ((irq = find_unbound_irq(cpu, false)) < 0) + goto out; + + bind_ipi.vcpu = cpu; +@@ -510,6 +562,7 @@ static int bind_ipi_to_irq(unsigned int + spin_unlock(&irq_mapping_update_lock); + return irq; + } ++#endif + + static void unbind_from_irq(unsigned int irq) + { +@@ -517,6 +570,7 @@ static void unbind_from_irq(unsigned int + unsigned int cpu; + int evtchn = evtchn_from_irq(irq); + ++ BUG_IF_IPI(irq); + spin_lock(&irq_mapping_update_lock); + + if (!--irq_cfg(irq)->bindcount && VALID_EVTCHN(evtchn)) { +@@ -530,10 +584,12 @@ static void unbind_from_irq(unsigned int + per_cpu(virq_to_irq, cpu_from_evtchn(evtchn)) + [index_from_irq(irq)] = -1; + break; ++#if defined(CONFIG_SMP) && defined(PER_CPU_IPI_IRQ) + case IRQT_IPI: + per_cpu(ipi_to_irq, cpu_from_evtchn(evtchn)) + [index_from_irq(irq)] = -1; + break; ++#endif + default: + break; + } +@@ -556,6 +612,46 @@ static void unbind_from_irq(unsigned int + spin_unlock(&irq_mapping_update_lock); + } + ++#if defined(CONFIG_SMP) && !defined(PER_CPU_IPI_IRQ) ++void unbind_from_per_cpu_irq(unsigned int irq, unsigned int cpu) ++{ ++ struct evtchn_close close; ++ int evtchn = evtchn_from_per_cpu_irq(irq, cpu); ++ ++ spin_lock(&irq_mapping_update_lock); ++ ++ if (VALID_EVTCHN(evtchn)) { ++ struct irq_desc *desc = irq_to_desc(irq); ++ ++ mask_evtchn(evtchn); ++ ++ BUG_ON(irq_cfg(irq)->bindcount <= 1); ++ irq_cfg(irq)->bindcount--; ++ cpumask_clear_cpu(cpu, desc->affinity); ++ ++ close.port = evtchn; ++ if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close)) ++ BUG(); ++ ++ switch (type_from_irq(irq)) { ++ case IRQT_IPI: ++ per_cpu(ipi_to_evtchn, cpu)[index_from_irq(irq)] = 0; ++ break; ++ default: ++ BUG(); ++ break; ++ } ++ ++ /* Closed ports are implicitly re-bound to VCPU0. */ ++ bind_evtchn_to_cpu(evtchn, 0); ++ ++ evtchn_to_irq[evtchn] = -1; ++ } ++ ++ spin_unlock(&irq_mapping_update_lock); ++} ++#endif /* CONFIG_SMP && !PER_CPU_IPI_IRQ */ ++ + int bind_caller_port_to_irqhandler( + unsigned int caller_port, + irq_handler_t handler, +@@ -650,6 +746,8 @@ int bind_virq_to_irqhandler( + } + EXPORT_SYMBOL_GPL(bind_virq_to_irqhandler); + ++#ifdef CONFIG_SMP ++#ifdef PER_CPU_IPI_IRQ + int bind_ipi_to_irqhandler( + unsigned int ipi, + unsigned int cpu, +@@ -673,7 +771,71 @@ int bind_ipi_to_irqhandler( + + return irq; + } +-EXPORT_SYMBOL_GPL(bind_ipi_to_irqhandler); ++#else ++int __cpuinit bind_ipi_to_irqaction( ++ unsigned int ipi, ++ unsigned int cpu, ++ struct irqaction *action) ++{ ++ struct evtchn_bind_ipi bind_ipi; ++ int evtchn, irq, retval = 0; ++ ++ spin_lock(&irq_mapping_update_lock); ++ ++ if (VALID_EVTCHN(per_cpu(ipi_to_evtchn, cpu)[ipi])) { ++ spin_unlock(&irq_mapping_update_lock); ++ return -EBUSY; ++ } ++ ++ if ((irq = ipi_to_irq[ipi]) == -1) { ++ if ((irq = find_unbound_irq(cpu, true)) < 0) { ++ spin_unlock(&irq_mapping_update_lock); ++ return irq; ++ } ++ ++ /* Extra reference so count will never drop to zero. */ ++ irq_cfg(irq)->bindcount++; ++ ++ ipi_to_irq[ipi] = irq; ++ irq_cfg(irq)->info = mk_irq_info(IRQT_IPI, ipi, 0); ++ retval = 1; ++ } ++ ++ bind_ipi.vcpu = cpu; ++ if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_ipi, ++ &bind_ipi) != 0) ++ BUG(); ++ ++ evtchn = bind_ipi.port; ++ evtchn_to_irq[evtchn] = irq; ++ per_cpu(ipi_to_evtchn, cpu)[ipi] = evtchn; ++ ++ bind_evtchn_to_cpu(evtchn, cpu); ++ ++ irq_cfg(irq)->bindcount++; ++ ++ spin_unlock(&irq_mapping_update_lock); ++ ++ if (retval == 0) { ++ unsigned long flags; ++ ++ local_irq_save(flags); ++ unmask_evtchn(evtchn); ++ local_irq_restore(flags); ++ } else { ++ action->flags |= IRQF_PERCPU | IRQF_NO_SUSPEND; ++ retval = setup_irq(irq, action); ++ if (retval) { ++ unbind_from_per_cpu_irq(irq, cpu); ++ BUG_ON(retval > 0); ++ irq = retval; ++ } ++ } ++ ++ return irq; ++} ++#endif /* PER_CPU_IPI_IRQ */ ++#endif /* CONFIG_SMP */ + + void unbind_from_irqhandler(unsigned int irq, void *dev_id) + { +@@ -699,6 +861,7 @@ static void rebind_irq_to_cpu(unsigned i + { + int evtchn = evtchn_from_irq(irq); + ++ BUG_IF_IPI(irq); + if (VALID_EVTCHN(evtchn)) + rebind_evtchn_to_cpu(evtchn, tcpu); + } +@@ -784,6 +947,7 @@ static struct irq_chip dynirq_chip = { + .unmask = unmask_dynirq, + .mask_ack = ack_dynirq, + .ack = ack_dynirq, ++ .eoi = end_dynirq, + .end = end_dynirq, + #ifdef CONFIG_SMP + .set_affinity = set_affinity_irq, +@@ -963,10 +1127,21 @@ int irq_ignore_unhandled(unsigned int ir + return !!(irq_status.flags & XENIRQSTAT_shared); + } + ++#if defined(CONFIG_SMP) && !defined(PER_CPU_IPI_IRQ) ++void notify_remote_via_ipi(unsigned int ipi, unsigned int cpu) ++{ ++ int evtchn = evtchn_from_per_cpu_irq(ipi_to_irq[ipi], cpu); ++ ++ if (VALID_EVTCHN(evtchn)) ++ notify_remote_via_evtchn(evtchn); ++} ++#endif ++ + void notify_remote_via_irq(int irq) + { + int evtchn = evtchn_from_irq(irq); + ++ BUG_IF_IPI(irq); + if (VALID_EVTCHN(evtchn)) + notify_remote_via_evtchn(evtchn); + } +@@ -974,6 +1149,7 @@ EXPORT_SYMBOL_GPL(notify_remote_via_irq) + + int irq_to_evtchn_port(int irq) + { ++ BUG_IF_IPI(irq); + return evtchn_from_irq(irq); + } + EXPORT_SYMBOL_GPL(irq_to_evtchn_port); +@@ -1089,11 +1265,17 @@ static void restore_cpu_virqs(unsigned i + + static void restore_cpu_ipis(unsigned int cpu) + { ++#ifdef CONFIG_SMP + struct evtchn_bind_ipi bind_ipi; + int ipi, irq, evtchn; + + for (ipi = 0; ipi < NR_IPIS; ipi++) { ++#ifdef PER_CPU_IPI_IRQ + if ((irq = per_cpu(ipi_to_irq, cpu)[ipi]) == -1) ++#else ++ if ((irq = ipi_to_irq[ipi]) == -1 ++ || !VALID_EVTCHN(per_cpu(ipi_to_evtchn, cpu)[ipi])) ++#endif + continue; + + BUG_ON(irq_cfg(irq)->info != mk_irq_info(IRQT_IPI, ipi, 0)); +@@ -1107,13 +1289,18 @@ static void restore_cpu_ipis(unsigned in + + /* Record the new mapping. */ + evtchn_to_irq[evtchn] = irq; ++#ifdef PER_CPU_IPI_IRQ + irq_cfg(irq)->info = mk_irq_info(IRQT_IPI, ipi, evtchn); ++#else ++ per_cpu(ipi_to_evtchn, cpu)[ipi] = evtchn; ++#endif + bind_evtchn_to_cpu(evtchn, cpu); + + /* Ready for use. */ + if (!(irq_to_desc(irq)->status & IRQ_DISABLED)) + unmask_evtchn(evtchn); + } ++#endif + } + + static int evtchn_resume(struct sys_device *dev) +--- sle11sp1-2010-03-29.orig/drivers/xen/core/smpboot.c 2010-03-22 12:57:24.000000000 +0100 ++++ sle11sp1-2010-03-29/drivers/xen/core/smpboot.c 2010-03-22 12:57:46.000000000 +0100 +@@ -40,14 +40,10 @@ cpumask_var_t vcpu_initialized_mask; + DEFINE_PER_CPU(struct cpuinfo_x86, cpu_info); + EXPORT_PER_CPU_SYMBOL(cpu_info); + +-static DEFINE_PER_CPU(int, resched_irq); +-static DEFINE_PER_CPU(int, callfunc_irq); +-static DEFINE_PER_CPU(int, call1func_irq); +-static DEFINE_PER_CPU(int, reboot_irq); +-static char resched_name[NR_CPUS][15]; +-static char callfunc_name[NR_CPUS][15]; +-static char call1func_name[NR_CPUS][15]; +-static char reboot_name[NR_CPUS][15]; ++static int __read_mostly resched_irq = -1; ++static int __read_mostly callfunc_irq = -1; ++static int __read_mostly call1func_irq = -1; ++static int __read_mostly reboot_irq = -1; + + #ifdef CONFIG_X86_LOCAL_APIC + #define set_cpu_to_apicid(cpu, apicid) (per_cpu(x86_cpu_to_apicid, cpu) = (apicid)) +@@ -109,58 +105,68 @@ remove_siblinginfo(unsigned int cpu) + + static int __cpuinit xen_smp_intr_init(unsigned int cpu) + { ++ static struct irqaction resched_action = { ++ .handler = smp_reschedule_interrupt, ++ .flags = IRQF_DISABLED, ++ .name = "resched" ++ }, callfunc_action = { ++ .handler = smp_call_function_interrupt, ++ .flags = IRQF_DISABLED, ++ .name = "callfunc" ++ }, call1func_action = { ++ .handler = smp_call_function_single_interrupt, ++ .flags = IRQF_DISABLED, ++ .name = "call1func" ++ }, reboot_action = { ++ .handler = smp_reboot_interrupt, ++ .flags = IRQF_DISABLED, ++ .name = "reboot" ++ }; + int rc; + +- per_cpu(resched_irq, cpu) = per_cpu(callfunc_irq, cpu) = +- per_cpu(call1func_irq, cpu) = per_cpu(reboot_irq, cpu) = -1; +- +- sprintf(resched_name[cpu], "resched%u", cpu); +- rc = bind_ipi_to_irqhandler(RESCHEDULE_VECTOR, +- cpu, +- smp_reschedule_interrupt, +- IRQF_DISABLED|IRQF_NOBALANCING, +- resched_name[cpu], +- NULL); ++ rc = bind_ipi_to_irqaction(RESCHEDULE_VECTOR, ++ cpu, ++ &resched_action); + if (rc < 0) +- goto fail; +- per_cpu(resched_irq, cpu) = rc; +- +- sprintf(callfunc_name[cpu], "callfunc%u", cpu); +- rc = bind_ipi_to_irqhandler(CALL_FUNCTION_VECTOR, +- cpu, +- smp_call_function_interrupt, +- IRQF_DISABLED|IRQF_NOBALANCING, +- callfunc_name[cpu], +- NULL); ++ return rc; ++ if (resched_irq < 0) ++ resched_irq = rc; ++ else ++ BUG_ON(resched_irq != rc); ++ ++ rc = bind_ipi_to_irqaction(CALL_FUNCTION_VECTOR, ++ cpu, ++ &callfunc_action); + if (rc < 0) +- goto fail; +- per_cpu(callfunc_irq, cpu) = rc; +- +- sprintf(call1func_name[cpu], "call1func%u", cpu); +- rc = bind_ipi_to_irqhandler(CALL_FUNC_SINGLE_VECTOR, +- cpu, +- smp_call_function_single_interrupt, +- IRQF_DISABLED|IRQF_NOBALANCING, +- call1func_name[cpu], +- NULL); ++ goto unbind_resched; ++ if (callfunc_irq < 0) ++ callfunc_irq = rc; ++ else ++ BUG_ON(callfunc_irq != rc); ++ ++ rc = bind_ipi_to_irqaction(CALL_FUNC_SINGLE_VECTOR, ++ cpu, ++ &call1func_action); + if (rc < 0) +- goto fail; +- per_cpu(call1func_irq, cpu) = rc; +- +- sprintf(reboot_name[cpu], "reboot%u", cpu); +- rc = bind_ipi_to_irqhandler(REBOOT_VECTOR, +- cpu, +- smp_reboot_interrupt, +- IRQF_DISABLED|IRQF_NOBALANCING, +- reboot_name[cpu], +- NULL); ++ goto unbind_call; ++ if (call1func_irq < 0) ++ call1func_irq = rc; ++ else ++ BUG_ON(call1func_irq != rc); ++ ++ rc = bind_ipi_to_irqaction(REBOOT_VECTOR, ++ cpu, ++ &reboot_action); + if (rc < 0) +- goto fail; +- per_cpu(reboot_irq, cpu) = rc; ++ goto unbind_call1; ++ if (reboot_irq < 0) ++ reboot_irq = rc; ++ else ++ BUG_ON(reboot_irq != rc); + + rc = xen_spinlock_init(cpu); + if (rc < 0) +- goto fail; ++ goto unbind_reboot; + + if ((cpu != 0) && ((rc = local_setup_timer(cpu)) != 0)) + goto fail; +@@ -168,15 +174,15 @@ static int __cpuinit xen_smp_intr_init(u + return 0; + + fail: +- if (per_cpu(resched_irq, cpu) >= 0) +- unbind_from_irqhandler(per_cpu(resched_irq, cpu), NULL); +- if (per_cpu(callfunc_irq, cpu) >= 0) +- unbind_from_irqhandler(per_cpu(callfunc_irq, cpu), NULL); +- if (per_cpu(call1func_irq, cpu) >= 0) +- unbind_from_irqhandler(per_cpu(call1func_irq, cpu), NULL); +- if (per_cpu(reboot_irq, cpu) >= 0) +- unbind_from_irqhandler(per_cpu(reboot_irq, cpu), NULL); + xen_spinlock_cleanup(cpu); ++ unbind_reboot: ++ unbind_from_per_cpu_irq(reboot_irq, cpu); ++ unbind_call1: ++ unbind_from_per_cpu_irq(call1func_irq, cpu); ++ unbind_call: ++ unbind_from_per_cpu_irq(callfunc_irq, cpu); ++ unbind_resched: ++ unbind_from_per_cpu_irq(resched_irq, cpu); + return rc; + } + +@@ -186,10 +192,10 @@ static void __cpuinit xen_smp_intr_exit( + if (cpu != 0) + local_teardown_timer(cpu); + +- unbind_from_irqhandler(per_cpu(resched_irq, cpu), NULL); +- unbind_from_irqhandler(per_cpu(callfunc_irq, cpu), NULL); +- unbind_from_irqhandler(per_cpu(call1func_irq, cpu), NULL); +- unbind_from_irqhandler(per_cpu(reboot_irq, cpu), NULL); ++ unbind_from_per_cpu_irq(resched_irq, cpu); ++ unbind_from_per_cpu_irq(callfunc_irq, cpu); ++ unbind_from_per_cpu_irq(call1func_irq, cpu); ++ unbind_from_per_cpu_irq(reboot_irq, cpu); + xen_spinlock_cleanup(cpu); + } + #endif +--- sle11sp1-2010-03-29.orig/drivers/xen/core/spinlock.c 2010-02-24 16:14:47.000000000 +0100 ++++ sle11sp1-2010-03-29/drivers/xen/core/spinlock.c 2010-02-23 14:25:31.000000000 +0100 +@@ -14,8 +14,7 @@ + + #ifdef TICKET_SHIFT + +-static DEFINE_PER_CPU(int, spinlock_irq) = -1; +-static char spinlock_name[NR_CPUS][15]; ++static int __read_mostly spinlock_irq = -1; + + struct spinning { + raw_spinlock_t *lock; +@@ -32,29 +31,31 @@ static DEFINE_PER_CPU(raw_rwlock_t, spin + + int __cpuinit xen_spinlock_init(unsigned int cpu) + { ++ static struct irqaction spinlock_action = { ++ .handler = smp_reschedule_interrupt, ++ .flags = IRQF_DISABLED, ++ .name = "spinlock" ++ }; + int rc; + +- sprintf(spinlock_name[cpu], "spinlock%u", cpu); +- rc = bind_ipi_to_irqhandler(SPIN_UNLOCK_VECTOR, +- cpu, +- smp_reschedule_interrupt, +- IRQF_DISABLED|IRQF_NOBALANCING, +- spinlock_name[cpu], +- NULL); ++ rc = bind_ipi_to_irqaction(SPIN_UNLOCK_VECTOR, ++ cpu, ++ &spinlock_action); + if (rc < 0) + return rc; + +- disable_irq(rc); /* make sure it's never delivered */ +- per_cpu(spinlock_irq, cpu) = rc; ++ if (spinlock_irq < 0) { ++ disable_irq(rc); /* make sure it's never delivered */ ++ spinlock_irq = rc; ++ } else ++ BUG_ON(spinlock_irq != rc); + + return 0; + } + + void __cpuinit xen_spinlock_cleanup(unsigned int cpu) + { +- if (per_cpu(spinlock_irq, cpu) >= 0) +- unbind_from_irqhandler(per_cpu(spinlock_irq, cpu), NULL); +- per_cpu(spinlock_irq, cpu) = -1; ++ unbind_from_per_cpu_irq(spinlock_irq, cpu); + } + + static unsigned int spin_adjust(struct spinning *spinning, +@@ -84,7 +85,7 @@ unsigned int xen_spin_adjust(const raw_s + bool xen_spin_wait(raw_spinlock_t *lock, unsigned int *ptok, + unsigned int flags) + { +- int irq = percpu_read(spinlock_irq); ++ int irq = spinlock_irq; + bool rc; + typeof(vcpu_info(0)->evtchn_upcall_mask) upcall_mask; + raw_rwlock_t *rm_lock; +@@ -240,7 +241,7 @@ void xen_spin_kick(raw_spinlock_t *lock, + raw_local_irq_restore(flags); + + if (unlikely(spinning)) { +- notify_remote_via_irq(per_cpu(spinlock_irq, cpu)); ++ notify_remote_via_ipi(SPIN_UNLOCK_VECTOR, cpu); + return; + } + } +--- sle11sp1-2010-03-29.orig/include/xen/evtchn.h 2009-12-18 10:13:12.000000000 +0100 ++++ sle11sp1-2010-03-29/include/xen/evtchn.h 2009-12-18 10:13:26.000000000 +0100 +@@ -92,6 +92,8 @@ int bind_virq_to_irqhandler( + unsigned long irqflags, + const char *devname, + void *dev_id); ++#if defined(CONFIG_SMP) && !defined(MODULE) ++#ifndef CONFIG_X86 + int bind_ipi_to_irqhandler( + unsigned int ipi, + unsigned int cpu, +@@ -99,6 +101,13 @@ int bind_ipi_to_irqhandler( + unsigned long irqflags, + const char *devname, + void *dev_id); ++#else ++int bind_ipi_to_irqaction( ++ unsigned int ipi, ++ unsigned int cpu, ++ struct irqaction *action); ++#endif ++#endif + + /* + * Common unbind function for all event sources. Takes IRQ to unbind from. +@@ -107,6 +116,11 @@ int bind_ipi_to_irqhandler( + */ + void unbind_from_irqhandler(unsigned int irq, void *dev_id); + ++#if defined(CONFIG_SMP) && !defined(MODULE) && defined(CONFIG_X86) ++/* Specialized unbind function for per-CPU IRQs. */ ++void unbind_from_per_cpu_irq(unsigned int irq, unsigned int cpu); ++#endif ++ + #ifndef CONFIG_XEN + void irq_resume(void); + #endif +@@ -184,5 +198,9 @@ void xen_poll_irq(int irq); + void notify_remote_via_irq(int irq); + int irq_to_evtchn_port(int irq); + ++#if defined(CONFIG_SMP) && !defined(MODULE) && defined(CONFIG_X86) ++void notify_remote_via_ipi(unsigned int ipi, unsigned int cpu); ++#endif ++ + #endif /* __ASM_EVTCHN_H__ */ + #endif /* CONFIG_PARAVIRT_XEN */ diff --git a/xen-kconfig-compat b/xen-kconfig-compat new file mode 100644 index 0000000..ca5b643 --- /dev/null +++ b/xen-kconfig-compat @@ -0,0 +1,32 @@ +From: jbeulich@novell.com +Subject: add 3.2.0-compatibility configure option +Patch-mainline: obsolete + +--- sle11sp1-2010-03-29.orig/drivers/xen/Kconfig 2010-03-29 09:12:44.000000000 +0200 ++++ sle11sp1-2010-03-29/drivers/xen/Kconfig 2010-03-29 09:12:59.000000000 +0200 +@@ -320,6 +320,15 @@ choice + config XEN_COMPAT_030100_AND_LATER + bool "3.1.0 and later" + ++ config XEN_COMPAT_030200_AND_LATER ++ bool "3.2.0 and later" ++ ++ config XEN_COMPAT_030300_AND_LATER ++ bool "3.3.0 and later" ++ ++ config XEN_COMPAT_030400_AND_LATER ++ bool "3.4.0 and later" ++ + config XEN_COMPAT_LATEST_ONLY + bool "no compatibility code" + +@@ -328,6 +337,9 @@ endchoice + config XEN_COMPAT + hex + default 0xffffff if XEN_COMPAT_LATEST_ONLY ++ default 0x030400 if XEN_COMPAT_030400_AND_LATER ++ default 0x030300 if XEN_COMPAT_030300_AND_LATER ++ default 0x030200 if XEN_COMPAT_030200_AND_LATER + default 0x030100 if XEN_COMPAT_030100_AND_LATER + default 0x030004 if XEN_COMPAT_030004_AND_LATER + default 0x030002 if XEN_COMPAT_030002_AND_LATER diff --git a/xen-modular-blktap b/xen-modular-blktap new file mode 100644 index 0000000..cbc56a1 --- /dev/null +++ b/xen-modular-blktap @@ -0,0 +1,27 @@ +From: ccoffing@novell.com +Subject: Retain backwards-compatible module name with CONFIG_XEN_BLKDEV_TAP=m +Patch-mainline: obsolete + +--- head-2009-05-29.orig/drivers/xen/blktap/Makefile 2007-06-12 13:13:44.000000000 +0200 ++++ head-2009-05-29/drivers/xen/blktap/Makefile 2009-05-29 12:39:04.000000000 +0200 +@@ -1,5 +1,5 @@ + LINUXINCLUDE += -I../xen/include/public/io + +-obj-$(CONFIG_XEN_BLKDEV_TAP) := xenblktap.o ++obj-$(CONFIG_XEN_BLKDEV_TAP) := blktap.o + +-xenblktap-y := xenbus.o interface.o blktap.o ++blktap-y := xenbus.o interface.o blocktap.o +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ head-2009-05-29/drivers/xen/blktap/blocktap.c 2009-05-29 12:39:04.000000000 +0200 +@@ -0,0 +1 @@ ++#include "blktap.c" +--- head-2009-05-29.orig/drivers/xen/blktap2/Makefile 2009-05-29 10:25:53.000000000 +0200 ++++ head-2009-05-29/drivers/xen/blktap2/Makefile 2009-05-29 12:39:04.000000000 +0200 +@@ -1,3 +1,4 @@ +-obj-$(CONFIG_XEN_BLKDEV_TAP2) := blktap.o ++obj-$(CONFIG_XEN_BLKDEV_TAP2) := blktap2.o + +-blktap-objs := control.o ring.o wait_queue.o device.o request.o sysfs.o ++blktap2-y := control.o ring.o wait_queue.o device.o request.o ++blktap2-$(CONFIG_SYSFS) += sysfs.o diff --git a/xen-netback-generalize b/xen-netback-generalize new file mode 100644 index 0000000..031aa57 --- /dev/null +++ b/xen-netback-generalize @@ -0,0 +1,1282 @@ +From: Dongxiao Xu +Subject: [PATCH 1/3] Netback: Generalize static/global variables into 'struct xen_netbk'. +Patch-mainline: n/a + + Put all the static/global variables in netback.c into xen_netback + structure. Do some preparations for the support of netback multiple + threads. + +Signed-off-by: Dongxiao Xu + +jb: various cleanups +Acked-by: jbeulich@novell.com + +--- sle11sp1-2010-01-27.orig/drivers/xen/netback/common.h 2010-01-29 12:48:08.000000000 +0100 ++++ sle11sp1-2010-01-27/drivers/xen/netback/common.h 2010-01-14 08:39:00.000000000 +0100 +@@ -217,4 +217,81 @@ static inline int netbk_can_sg(struct ne + return netif->features & NETIF_F_SG; + } + ++struct pending_tx_info { ++ netif_tx_request_t req; ++ netif_t *netif; ++}; ++typedef unsigned int pending_ring_idx_t; ++ ++struct page_ext { ++ unsigned int group; ++ unsigned int idx; ++}; ++ ++struct netbk_rx_meta { ++ skb_frag_t frag; ++ int id; ++ u8 copy:1; ++}; ++ ++struct netbk_tx_pending_inuse { ++ struct list_head list; ++ unsigned long alloc_time; ++}; ++ ++#define MAX_PENDING_REQS (1U << CONFIG_XEN_NETDEV_TX_SHIFT) ++#define MAX_MFN_ALLOC 64 ++ ++struct xen_netbk { ++ struct tasklet_struct net_tx_tasklet; ++ struct tasklet_struct net_rx_tasklet; ++ ++ struct sk_buff_head rx_queue; ++ struct sk_buff_head tx_queue; ++ ++ struct timer_list net_timer; ++ struct timer_list tx_pending_timer; ++ ++ pending_ring_idx_t pending_prod; ++ pending_ring_idx_t pending_cons; ++ pending_ring_idx_t dealloc_prod; ++ pending_ring_idx_t dealloc_cons; ++ ++ struct list_head pending_inuse_head; ++ struct list_head net_schedule_list; ++ ++ spinlock_t net_schedule_list_lock; ++ spinlock_t release_lock; ++ ++ struct page **mmap_pages; ++ ++ unsigned int alloc_index; ++ ++ struct page_ext page_extinfo[MAX_PENDING_REQS]; ++ ++ struct pending_tx_info pending_tx_info[MAX_PENDING_REQS]; ++ struct netbk_tx_pending_inuse pending_inuse[MAX_PENDING_REQS]; ++ struct gnttab_unmap_grant_ref tx_unmap_ops[MAX_PENDING_REQS]; ++ struct gnttab_map_grant_ref tx_map_ops[MAX_PENDING_REQS]; ++ ++ grant_handle_t grant_tx_handle[MAX_PENDING_REQS]; ++ u16 pending_ring[MAX_PENDING_REQS]; ++ u16 dealloc_ring[MAX_PENDING_REQS]; ++ ++ struct multicall_entry rx_mcl[NET_RX_RING_SIZE+3]; ++ struct mmu_update rx_mmu[NET_RX_RING_SIZE]; ++ struct gnttab_transfer grant_trans_op[NET_RX_RING_SIZE]; ++ struct gnttab_copy grant_copy_op[NET_RX_RING_SIZE]; ++ DECLARE_BITMAP(rx_notify, NR_DYNIRQS); ++#if !defined(NR_DYNIRQS) ++# error ++#elif NR_DYNIRQS <= 0x10000 ++ u16 notify_list[NET_RX_RING_SIZE]; ++#else ++ int notify_list[NET_RX_RING_SIZE]; ++#endif ++ struct netbk_rx_meta meta[NET_RX_RING_SIZE]; ++ ++ unsigned long mfn_list[MAX_MFN_ALLOC]; ++}; + #endif /* __NETIF__BACKEND__COMMON_H__ */ +--- sle11sp1-2010-01-27.orig/drivers/xen/netback/netback.c 2010-01-29 12:48:08.000000000 +0100 ++++ sle11sp1-2010-01-27/drivers/xen/netback/netback.c 2010-01-29 12:51:48.000000000 +0100 +@@ -35,23 +35,18 @@ + */ + + #include "common.h" ++#include + #include + #include + + /*define NETBE_DEBUG_INTERRUPT*/ + +-struct netbk_rx_meta { +- skb_frag_t frag; +- int id; +- u8 copy:1; +-}; ++static struct xen_netbk *xen_netbk; ++static unsigned int netbk_nr_groups = 1; + +-struct netbk_tx_pending_inuse { +- struct list_head list; +- unsigned long alloc_time; +-}; ++#define GET_GROUP_INDEX(netif) (0) + +-static void netif_idx_release(u16 pending_idx); ++static void netif_idx_release(struct xen_netbk *, u16 pending_idx); + static void make_tx_response(netif_t *netif, + netif_tx_request_t *txp, + s8 st); +@@ -62,81 +57,34 @@ static netif_rx_response_t *make_rx_resp + u16 size, + u16 flags); + +-static void net_tx_action(unsigned long unused); +-static DECLARE_TASKLET(net_tx_tasklet, net_tx_action, 0); +- +-static void net_rx_action(unsigned long unused); +-static DECLARE_TASKLET(net_rx_tasklet, net_rx_action, 0); +- +-static struct timer_list net_timer; +-static struct timer_list netbk_tx_pending_timer; ++static void net_tx_action(unsigned long group); ++static void net_rx_action(unsigned long group); + +-#define MAX_PENDING_REQS (1U << CONFIG_XEN_NETDEV_TX_SHIFT) +- +-static struct sk_buff_head rx_queue; +- +-static struct page **mmap_pages; +-static inline unsigned long idx_to_pfn(unsigned int idx) ++static inline unsigned long idx_to_pfn(struct xen_netbk *netbk, unsigned int idx) + { +- return page_to_pfn(mmap_pages[idx]); ++ return page_to_pfn(netbk->mmap_pages[idx]); + } + +-static inline unsigned long idx_to_kaddr(unsigned int idx) ++static inline unsigned long idx_to_kaddr(struct xen_netbk *netbk, unsigned int idx) + { +- return (unsigned long)pfn_to_kaddr(idx_to_pfn(idx)); ++ return (unsigned long)pfn_to_kaddr(idx_to_pfn(netbk, idx)); + } + + /* extra field used in struct page */ +-static inline void netif_set_page_index(struct page *pg, unsigned int index) +-{ +- *(unsigned long *)&pg->mapping = index; +-} +- +-static inline int netif_page_index(struct page *pg) ++static inline void netif_set_page_ext(struct page *pg, struct page_ext *ext) + { +- unsigned long idx = (unsigned long)pg->mapping; +- +- if (!PageForeign(pg)) +- return -1; +- +- if ((idx >= MAX_PENDING_REQS) || (mmap_pages[idx] != pg)) +- return -1; +- +- return idx; ++ pg->mapping = (void *)ext; + } + + #define PKT_PROT_LEN 64 + +-static struct pending_tx_info { +- netif_tx_request_t req; +- netif_t *netif; +-} pending_tx_info[MAX_PENDING_REQS]; +-static u16 pending_ring[MAX_PENDING_REQS]; +-typedef unsigned int PEND_RING_IDX; + #define MASK_PEND_IDX(_i) ((_i)&(MAX_PENDING_REQS-1)) +-static PEND_RING_IDX pending_prod, pending_cons; +-#define NR_PENDING_REQS (MAX_PENDING_REQS - pending_prod + pending_cons) +- +-/* Freed TX SKBs get batched on this ring before return to pending_ring. */ +-static u16 dealloc_ring[MAX_PENDING_REQS]; +-static PEND_RING_IDX dealloc_prod, dealloc_cons; + +-/* Doubly-linked list of in-use pending entries. */ +-static struct netbk_tx_pending_inuse pending_inuse[MAX_PENDING_REQS]; +-static LIST_HEAD(pending_inuse_head); +- +-static struct sk_buff_head tx_queue; +- +-static grant_handle_t grant_tx_handle[MAX_PENDING_REQS]; +-static gnttab_unmap_grant_ref_t tx_unmap_ops[MAX_PENDING_REQS]; +-static gnttab_map_grant_ref_t tx_map_ops[MAX_PENDING_REQS]; +- +-static struct list_head net_schedule_list; +-static spinlock_t net_schedule_list_lock; +- +-#define MAX_MFN_ALLOC 64 +-static unsigned long mfn_list[MAX_MFN_ALLOC]; +-static unsigned int alloc_index = 0; ++static inline pending_ring_idx_t nr_pending_reqs(const struct xen_netbk *netbk) ++{ ++ return MAX_PENDING_REQS - ++ netbk->pending_prod + netbk->pending_cons; ++} + + /* Setting this allows the safe use of this driver without netloop. */ + static int MODPARM_copy_skb = 1; +@@ -148,13 +96,13 @@ MODULE_PARM_DESC(permute_returns, "Rando + + int netbk_copy_skb_mode; + +-static inline unsigned long alloc_mfn(void) ++static inline unsigned long alloc_mfn(struct xen_netbk *netbk) + { +- BUG_ON(alloc_index == 0); +- return mfn_list[--alloc_index]; ++ BUG_ON(netbk->alloc_index == 0); ++ return netbk->mfn_list[--netbk->alloc_index]; + } + +-static int check_mfn(int nr) ++static int check_mfn(struct xen_netbk *netbk, unsigned int nr) + { + struct xen_memory_reservation reservation = { + .extent_order = 0, +@@ -162,24 +110,27 @@ static int check_mfn(int nr) + }; + int rc; + +- if (likely(alloc_index >= nr)) ++ if (likely(netbk->alloc_index >= nr)) + return 0; + +- set_xen_guest_handle(reservation.extent_start, mfn_list + alloc_index); +- reservation.nr_extents = MAX_MFN_ALLOC - alloc_index; ++ set_xen_guest_handle(reservation.extent_start, ++ netbk->mfn_list + netbk->alloc_index); ++ reservation.nr_extents = MAX_MFN_ALLOC - netbk->alloc_index; + rc = HYPERVISOR_memory_op(XENMEM_increase_reservation, &reservation); + if (likely(rc > 0)) +- alloc_index += rc; ++ netbk->alloc_index += rc; + +- return alloc_index >= nr ? 0 : -ENOMEM; ++ return netbk->alloc_index >= nr ? 0 : -ENOMEM; + } + +-static inline void maybe_schedule_tx_action(void) ++static inline void maybe_schedule_tx_action(unsigned int group) + { ++ struct xen_netbk *netbk = &xen_netbk[group]; ++ + smp_mb(); +- if ((NR_PENDING_REQS < (MAX_PENDING_REQS/2)) && +- !list_empty(&net_schedule_list)) +- tasklet_schedule(&net_tx_tasklet); ++ if ((nr_pending_reqs(netbk) < (MAX_PENDING_REQS/2)) && ++ !list_empty(&netbk->net_schedule_list)) ++ tasklet_schedule(&netbk->net_tx_tasklet); + } + + static struct sk_buff *netbk_copy_skb(struct sk_buff *skb) +@@ -288,6 +239,7 @@ static void tx_queue_callback(unsigned l + int netif_be_start_xmit(struct sk_buff *skb, struct net_device *dev) + { + netif_t *netif = netdev_priv(dev); ++ struct xen_netbk *netbk; + + BUG_ON(skb->dev != dev); + +@@ -337,8 +289,9 @@ int netif_be_start_xmit(struct sk_buff * + } + } + +- skb_queue_tail(&rx_queue, skb); +- tasklet_schedule(&net_rx_tasklet); ++ netbk = &xen_netbk[GET_GROUP_INDEX(netif)]; ++ skb_queue_tail(&netbk->rx_queue, skb); ++ tasklet_schedule(&netbk->net_rx_tasklet); + + return NETDEV_TX_OK; + +@@ -393,19 +346,32 @@ static u16 netbk_gop_frag(netif_t *netif + multicall_entry_t *mcl; + netif_rx_request_t *req; + unsigned long old_mfn, new_mfn; +- int idx = netif_page_index(page); ++ struct xen_netbk *netbk = &xen_netbk[GET_GROUP_INDEX(netif)]; + + old_mfn = virt_to_mfn(page_address(page)); + + req = RING_GET_REQUEST(&netif->rx, netif->rx.req_cons + i); + if (netif->copying_receiver) { ++ struct page_ext *ext; ++ + /* The fragment needs to be copied rather than + flipped. */ + meta->copy = 1; + copy_gop = npo->copy + npo->copy_prod++; + copy_gop->flags = GNTCOPY_dest_gref; +- if (idx > -1) { +- struct pending_tx_info *src_pend = &pending_tx_info[idx]; ++ if (PageForeign(page) && ++ (ext = (void *)page->mapping) != NULL && ++ ext->idx < MAX_PENDING_REQS && ++ ext->group < netbk_nr_groups) { ++ struct pending_tx_info *src_pend; ++ ++ netbk = &xen_netbk[ext->group]; ++ BUG_ON(ext < netbk->page_extinfo || ++ ext >= netbk->page_extinfo + ++ ARRAY_SIZE(netbk->page_extinfo)); ++ BUG_ON(netbk->mmap_pages[ext->idx] != page); ++ src_pend = &netbk->pending_tx_info[ext->idx]; ++ BUG_ON(ext->group != GET_GROUP_INDEX(src_pend->netif)); + copy_gop->source.domid = src_pend->netif->domid; + copy_gop->source.u.ref = src_pend->req.gref; + copy_gop->flags |= GNTCOPY_source_gref; +@@ -421,7 +387,7 @@ static u16 netbk_gop_frag(netif_t *netif + } else { + meta->copy = 0; + if (!xen_feature(XENFEAT_auto_translated_physmap)) { +- new_mfn = alloc_mfn(); ++ new_mfn = alloc_mfn(netbk); + + /* + * Set the new P2M table entry before +@@ -566,7 +532,7 @@ static void netbk_add_frag_responses(net + } + } + +-static void net_rx_action(unsigned long unused) ++static void net_rx_action(unsigned long group) + { + netif_t *netif = NULL; + s8 status; +@@ -576,52 +542,37 @@ static void net_rx_action(unsigned long + struct sk_buff_head rxq; + struct sk_buff *skb; + int notify_nr = 0; +- int ret; ++ int ret, eagain; + int nr_frags; + int count; + unsigned long offset; +- int eagain; +- +- /* +- * Putting hundreds of bytes on the stack is considered rude. +- * Static works because a tasklet can only be on one CPU at any time. +- */ +- static multicall_entry_t rx_mcl[NET_RX_RING_SIZE+3]; +- static mmu_update_t rx_mmu[NET_RX_RING_SIZE]; +- static gnttab_transfer_t grant_trans_op[NET_RX_RING_SIZE]; +- static gnttab_copy_t grant_copy_op[NET_RX_RING_SIZE]; +- static DECLARE_BITMAP(rx_notify, NR_DYNIRQS); +-#if NR_DYNIRQS <= 0x10000 +- static u16 notify_list[NET_RX_RING_SIZE]; +-#else +- static int notify_list[NET_RX_RING_SIZE]; +-#endif +- static struct netbk_rx_meta meta[NET_RX_RING_SIZE]; ++ struct xen_netbk *netbk = &xen_netbk[group]; + + struct netrx_pending_operations npo = { +- mmu: rx_mmu, +- trans: grant_trans_op, +- copy: grant_copy_op, +- mcl: rx_mcl, +- meta: meta}; ++ .mmu = netbk->rx_mmu, ++ .trans = netbk->grant_trans_op, ++ .copy = netbk->grant_copy_op, ++ .mcl = netbk->rx_mcl, ++ .meta = netbk->meta, ++ }; + + skb_queue_head_init(&rxq); + + count = 0; + +- while ((skb = skb_dequeue(&rx_queue)) != NULL) { ++ while ((skb = skb_dequeue(&netbk->rx_queue)) != NULL) { + nr_frags = skb_shinfo(skb)->nr_frags; + *(int *)skb->cb = nr_frags; + + if (!xen_feature(XENFEAT_auto_translated_physmap) && + !((netif_t *)netdev_priv(skb->dev))->copying_receiver && +- check_mfn(nr_frags + 1)) { ++ check_mfn(netbk, nr_frags + 1)) { + /* Memory squeeze? Back off for an arbitrary while. */ + if ( net_ratelimit() ) + WPRINTK("Memory squeeze in netback " + "driver.\n"); +- mod_timer(&net_timer, jiffies + HZ); +- skb_queue_head(&rx_queue, skb); ++ mod_timer(&netbk->net_timer, jiffies + HZ); ++ skb_queue_head(&netbk->rx_queue, skb); + break; + } + +@@ -636,39 +587,39 @@ static void net_rx_action(unsigned long + break; + } + +- BUG_ON(npo.meta_prod > ARRAY_SIZE(meta)); ++ BUG_ON(npo.meta_prod > ARRAY_SIZE(netbk->meta)); + + npo.mmu_mcl = npo.mcl_prod; + if (npo.mcl_prod) { + BUG_ON(xen_feature(XENFEAT_auto_translated_physmap)); +- BUG_ON(npo.mmu_prod > ARRAY_SIZE(rx_mmu)); ++ BUG_ON(npo.mmu_prod > ARRAY_SIZE(netbk->rx_mmu)); + mcl = npo.mcl + npo.mcl_prod++; + + BUG_ON(mcl[-1].op != __HYPERVISOR_update_va_mapping); + mcl[-1].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL; + + mcl->op = __HYPERVISOR_mmu_update; +- mcl->args[0] = (unsigned long)rx_mmu; ++ mcl->args[0] = (unsigned long)netbk->rx_mmu; + mcl->args[1] = npo.mmu_prod; + mcl->args[2] = 0; + mcl->args[3] = DOMID_SELF; + } + + if (npo.trans_prod) { +- BUG_ON(npo.trans_prod > ARRAY_SIZE(grant_trans_op)); ++ BUG_ON(npo.trans_prod > ARRAY_SIZE(netbk->grant_trans_op)); + mcl = npo.mcl + npo.mcl_prod++; + mcl->op = __HYPERVISOR_grant_table_op; + mcl->args[0] = GNTTABOP_transfer; +- mcl->args[1] = (unsigned long)grant_trans_op; ++ mcl->args[1] = (unsigned long)netbk->grant_trans_op; + mcl->args[2] = npo.trans_prod; + } + + if (npo.copy_prod) { +- BUG_ON(npo.copy_prod > ARRAY_SIZE(grant_copy_op)); ++ BUG_ON(npo.copy_prod > ARRAY_SIZE(netbk->grant_copy_op)); + mcl = npo.mcl + npo.mcl_prod++; + mcl->op = __HYPERVISOR_grant_table_op; + mcl->args[0] = GNTTABOP_copy; +- mcl->args[1] = (unsigned long)grant_copy_op; ++ mcl->args[1] = (unsigned long)netbk->grant_copy_op; + mcl->args[2] = npo.copy_prod; + } + +@@ -676,7 +627,7 @@ static void net_rx_action(unsigned long + if (!npo.mcl_prod) + return; + +- BUG_ON(npo.mcl_prod > ARRAY_SIZE(rx_mcl)); ++ BUG_ON(npo.mcl_prod > ARRAY_SIZE(netbk->rx_mcl)); + + ret = HYPERVISOR_multicall(npo.mcl, npo.mcl_prod); + BUG_ON(ret != 0); +@@ -707,7 +658,7 @@ static void net_rx_action(unsigned long + atomic_set(&(skb_shinfo(skb)->dataref), 1); + skb_shinfo(skb)->frag_list = NULL; + skb_shinfo(skb)->nr_frags = 0; +- netbk_free_pages(nr_frags, meta + npo.meta_cons + 1); ++ netbk_free_pages(nr_frags, netbk->meta + npo.meta_cons + 1); + } + + if(!eagain) +@@ -716,7 +667,7 @@ static void net_rx_action(unsigned long + netif->stats.tx_packets++; + } + +- id = meta[npo.meta_cons].id; ++ id = netbk->meta[npo.meta_cons].id; + flags = nr_frags ? NETRXF_more_data : 0; + + if (skb->ip_summed == CHECKSUM_PARTIAL) /* local packet? */ +@@ -724,14 +675,14 @@ static void net_rx_action(unsigned long + else if (skb->proto_data_valid) /* remote but checksummed? */ + flags |= NETRXF_data_validated; + +- if (meta[npo.meta_cons].copy) ++ if (netbk->meta[npo.meta_cons].copy) + offset = 0; + else + offset = offset_in_page(skb->data); + resp = make_rx_response(netif, id, status, offset, + skb_headlen(skb), flags); + +- if (meta[npo.meta_cons].frag.size) { ++ if (netbk->meta[npo.meta_cons].frag.size) { + struct netif_extra_info *gso = + (struct netif_extra_info *) + RING_GET_RESPONSE(&netif->rx, +@@ -739,7 +690,7 @@ static void net_rx_action(unsigned long + + resp->flags |= NETRXF_extra_info; + +- gso->u.gso.size = meta[npo.meta_cons].frag.size; ++ gso->u.gso.size = netbk->meta[npo.meta_cons].frag.size; + gso->u.gso.type = XEN_NETIF_GSO_TYPE_TCPV4; + gso->u.gso.pad = 0; + gso->u.gso.features = 0; +@@ -749,13 +700,13 @@ static void net_rx_action(unsigned long + } + + netbk_add_frag_responses(netif, status, +- meta + npo.meta_cons + 1, ++ netbk->meta + npo.meta_cons + 1, + nr_frags); + + RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&netif->rx, ret); + irq = netif->irq - DYNIRQ_BASE; +- if (ret && !__test_and_set_bit(irq, rx_notify)) +- notify_list[notify_nr++] = irq; ++ if (ret && !__test_and_set_bit(irq, netbk->rx_notify)) ++ netbk->notify_list[notify_nr++] = irq; + + if (netif_queue_stopped(netif->dev) && + netif_schedulable(netif) && +@@ -772,45 +723,46 @@ static void net_rx_action(unsigned long + { + netif->rx_req_cons_peek += skb_shinfo(skb)->nr_frags + 1 + + !!skb_shinfo(skb)->gso_size; +- skb_queue_head(&rx_queue, skb); ++ skb_queue_head(&netbk->rx_queue, skb); + } + + npo.meta_cons += nr_frags + 1; + } + + if (notify_nr == 1) { +- irq = *notify_list; +- __clear_bit(irq, rx_notify); ++ irq = *netbk->notify_list; ++ __clear_bit(irq, netbk->rx_notify); + notify_remote_via_irq(irq + DYNIRQ_BASE); + } else { + for (count = ret = 0; ret < notify_nr; ++ret) { +- irq = notify_list[ret]; +- __clear_bit(irq, rx_notify); +- if (!multi_notify_remote_via_irq(rx_mcl + count, ++ irq = netbk->notify_list[ret]; ++ __clear_bit(irq, netbk->rx_notify); ++ if (!multi_notify_remote_via_irq(netbk->rx_mcl + count, + irq + DYNIRQ_BASE)) + ++count; + } +- if (HYPERVISOR_multicall(rx_mcl, count)) ++ if (HYPERVISOR_multicall(netbk->rx_mcl, count)) + BUG(); + } + + /* More work to do? */ +- if (!skb_queue_empty(&rx_queue) && !timer_pending(&net_timer)) +- tasklet_schedule(&net_rx_tasklet); ++ if (!skb_queue_empty(&netbk->rx_queue) && ++ !timer_pending(&netbk->net_timer)) ++ tasklet_schedule(&netbk->net_rx_tasklet); + #if 0 + else + xen_network_done_notify(); + #endif + } + +-static void net_alarm(unsigned long unused) ++static void net_alarm(unsigned long group) + { +- tasklet_schedule(&net_rx_tasklet); ++ tasklet_schedule(&xen_netbk[group].net_rx_tasklet); + } + +-static void netbk_tx_pending_timeout(unsigned long unused) ++static void netbk_tx_pending_timeout(unsigned long group) + { +- tasklet_schedule(&net_tx_tasklet); ++ tasklet_schedule(&xen_netbk[group].net_tx_tasklet); + } + + struct net_device_stats *netif_be_get_stats(struct net_device *dev) +@@ -826,27 +778,31 @@ static int __on_net_schedule_list(netif_ + + static void remove_from_net_schedule_list(netif_t *netif) + { +- spin_lock_irq(&net_schedule_list_lock); ++ struct xen_netbk *netbk = &xen_netbk[GET_GROUP_INDEX(netif)]; ++ ++ spin_lock_irq(&netbk->net_schedule_list_lock); + if (likely(__on_net_schedule_list(netif))) { + list_del(&netif->list); + netif->list.next = NULL; + netif_put(netif); + } +- spin_unlock_irq(&net_schedule_list_lock); ++ spin_unlock_irq(&netbk->net_schedule_list_lock); + } + + static void add_to_net_schedule_list_tail(netif_t *netif) + { ++ struct xen_netbk *netbk = &xen_netbk[GET_GROUP_INDEX(netif)]; ++ + if (__on_net_schedule_list(netif)) + return; + +- spin_lock_irq(&net_schedule_list_lock); ++ spin_lock_irq(&netbk->net_schedule_list_lock); + if (!__on_net_schedule_list(netif) && + likely(netif_schedulable(netif))) { +- list_add_tail(&netif->list, &net_schedule_list); ++ list_add_tail(&netif->list, &netbk->net_schedule_list); + netif_get(netif); + } +- spin_unlock_irq(&net_schedule_list_lock); ++ spin_unlock_irq(&netbk->net_schedule_list_lock); + } + + /* +@@ -869,7 +825,7 @@ void netif_schedule_work(netif_t *netif) + + if (more_to_do) { + add_to_net_schedule_list_tail(netif); +- maybe_schedule_tx_action(); ++ maybe_schedule_tx_action(GET_GROUP_INDEX(netif)); + } + } + +@@ -906,17 +862,19 @@ static void tx_credit_callback(unsigned + netif_schedule_work(netif); + } + +-static inline int copy_pending_req(PEND_RING_IDX pending_idx) ++static inline int copy_pending_req(struct xen_netbk *netbk, ++ pending_ring_idx_t pending_idx) + { +- return gnttab_copy_grant_page(grant_tx_handle[pending_idx], +- &mmap_pages[pending_idx]); ++ return gnttab_copy_grant_page(netbk->grant_tx_handle[pending_idx], ++ &netbk->mmap_pages[pending_idx]); + } + +-static void permute_dealloc_ring(PEND_RING_IDX dc, PEND_RING_IDX dp) ++static void permute_dealloc_ring(u16 *dealloc_ring, pending_ring_idx_t dc, ++ pending_ring_idx_t dp) + { + static unsigned random_src = 0x12345678; + unsigned dst_offset; +- PEND_RING_IDX dest; ++ pending_ring_idx_t dest; + u16 tmp; + + while (dc != dp) { +@@ -931,62 +889,67 @@ static void permute_dealloc_ring(PEND_RI + } + } + +-inline static void net_tx_action_dealloc(void) ++inline static void net_tx_action_dealloc(struct xen_netbk *netbk) + { + struct netbk_tx_pending_inuse *inuse, *n; + gnttab_unmap_grant_ref_t *gop; + u16 pending_idx; +- PEND_RING_IDX dc, dp; ++ pending_ring_idx_t dc, dp; + netif_t *netif; + int ret; + LIST_HEAD(list); + +- dc = dealloc_cons; +- gop = tx_unmap_ops; ++ dc = netbk->dealloc_cons; ++ gop = netbk->tx_unmap_ops; + + /* + * Free up any grants we have finished using + */ + do { +- dp = dealloc_prod; ++ dp = netbk->dealloc_prod; + + /* Ensure we see all indices enqueued by netif_idx_release(). */ + smp_rmb(); + + if (MODPARM_permute_returns) +- permute_dealloc_ring(dc, dp); ++ permute_dealloc_ring(netbk->dealloc_ring, dc, dp); + + while (dc != dp) { + unsigned long pfn; ++ struct netbk_tx_pending_inuse *pending_inuse = ++ netbk->pending_inuse; + +- pending_idx = dealloc_ring[MASK_PEND_IDX(dc++)]; ++ pending_idx = netbk->dealloc_ring[MASK_PEND_IDX(dc++)]; + list_move_tail(&pending_inuse[pending_idx].list, &list); + +- pfn = idx_to_pfn(pending_idx); ++ pfn = idx_to_pfn(netbk, pending_idx); + /* Already unmapped? */ + if (!phys_to_machine_mapping_valid(pfn)) + continue; + +- gnttab_set_unmap_op(gop, idx_to_kaddr(pending_idx), ++ gnttab_set_unmap_op(gop, idx_to_kaddr(netbk, pending_idx), + GNTMAP_host_map, +- grant_tx_handle[pending_idx]); ++ netbk->grant_tx_handle[pending_idx]); + gop++; + } + + if (netbk_copy_skb_mode != NETBK_DELAYED_COPY_SKB || +- list_empty(&pending_inuse_head)) ++ list_empty(&netbk->pending_inuse_head)) + break; + + /* Copy any entries that have been pending for too long. */ +- list_for_each_entry_safe(inuse, n, &pending_inuse_head, list) { ++ list_for_each_entry_safe(inuse, n, &netbk->pending_inuse_head, list) { ++ struct pending_tx_info *pending_tx_info ++ = netbk->pending_tx_info; ++ + if (time_after(inuse->alloc_time + HZ / 2, jiffies)) + break; + +- pending_idx = inuse - pending_inuse; ++ pending_idx = inuse - netbk->pending_inuse; + + pending_tx_info[pending_idx].netif->nr_copied_skbs++; + +- switch (copy_pending_req(pending_idx)) { ++ switch (copy_pending_req(netbk, pending_idx)) { + case 0: + list_move_tail(&inuse->list, &list); + continue; +@@ -999,26 +962,30 @@ inline static void net_tx_action_dealloc + + break; + } +- } while (dp != dealloc_prod); ++ } while (dp != netbk->dealloc_prod); + +- dealloc_cons = dc; ++ netbk->dealloc_cons = dc; + + ret = HYPERVISOR_grant_table_op( +- GNTTABOP_unmap_grant_ref, tx_unmap_ops, gop - tx_unmap_ops); ++ GNTTABOP_unmap_grant_ref, netbk->tx_unmap_ops, ++ gop - netbk->tx_unmap_ops); + BUG_ON(ret); + + list_for_each_entry_safe(inuse, n, &list, list) { +- pending_idx = inuse - pending_inuse; ++ struct pending_tx_info *pending_tx_info = ++ netbk->pending_tx_info; + ++ pending_idx = inuse - netbk->pending_inuse; + netif = pending_tx_info[pending_idx].netif; + + make_tx_response(netif, &pending_tx_info[pending_idx].req, + NETIF_RSP_OKAY); + + /* Ready for next use. */ +- gnttab_reset_grant_page(mmap_pages[pending_idx]); ++ gnttab_reset_grant_page(netbk->mmap_pages[pending_idx]); + +- pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx; ++ netbk->pending_ring[MASK_PEND_IDX(netbk->pending_prod++)] = ++ pending_idx; + + netif_put(netif); + +@@ -1095,9 +1062,14 @@ static gnttab_map_grant_ref_t *netbk_get + start = ((unsigned long)shinfo->frags[0].page == pending_idx); + + for (i = start; i < shinfo->nr_frags; i++, txp++) { +- pending_idx = pending_ring[MASK_PEND_IDX(pending_cons++)]; ++ struct xen_netbk *netbk = &xen_netbk[GET_GROUP_INDEX(netif)]; ++ pending_ring_idx_t index = MASK_PEND_IDX(netbk->pending_cons++); ++ struct pending_tx_info *pending_tx_info = ++ netbk->pending_tx_info; ++ ++ pending_idx = netbk->pending_ring[index]; + +- gnttab_set_map_op(mop++, idx_to_kaddr(pending_idx), ++ gnttab_set_map_op(mop++, idx_to_kaddr(netbk, pending_idx), + GNTMAP_host_map | GNTMAP_readonly, + txp->gref, netif->domid); + +@@ -1110,11 +1082,12 @@ static gnttab_map_grant_ref_t *netbk_get + return mop; + } + +-static int netbk_tx_check_mop(struct sk_buff *skb, +- gnttab_map_grant_ref_t **mopp) ++static int netbk_tx_check_mop(struct xen_netbk *netbk, struct sk_buff *skb, ++ gnttab_map_grant_ref_t **mopp) + { + gnttab_map_grant_ref_t *mop = *mopp; + int pending_idx = *((u16 *)skb->data); ++ struct pending_tx_info *pending_tx_info = netbk->pending_tx_info; + netif_t *netif = pending_tx_info[pending_idx].netif; + netif_tx_request_t *txp; + struct skb_shared_info *shinfo = skb_shinfo(skb); +@@ -1124,14 +1097,16 @@ static int netbk_tx_check_mop(struct sk_ + /* Check status of header. */ + err = mop->status; + if (unlikely(err)) { ++ pending_ring_idx_t index = MASK_PEND_IDX(netbk->pending_prod++); ++ + txp = &pending_tx_info[pending_idx].req; + make_tx_response(netif, txp, NETIF_RSP_ERROR); +- pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx; ++ netbk->pending_ring[index] = pending_idx; + netif_put(netif); + } else { +- set_phys_to_machine(idx_to_pfn(pending_idx), ++ set_phys_to_machine(idx_to_pfn(netbk, pending_idx), + FOREIGN_FRAME(mop->dev_bus_addr >> PAGE_SHIFT)); +- grant_tx_handle[pending_idx] = mop->handle; ++ netbk->grant_tx_handle[pending_idx] = mop->handle; + } + + /* Skip first skb fragment if it is on same page as header fragment. */ +@@ -1139,25 +1114,27 @@ static int netbk_tx_check_mop(struct sk_ + + for (i = start; i < nr_frags; i++) { + int j, newerr; ++ pending_ring_idx_t index; + + pending_idx = (unsigned long)shinfo->frags[i].page; + + /* Check error status: if okay then remember grant handle. */ + newerr = (++mop)->status; + if (likely(!newerr)) { +- set_phys_to_machine(idx_to_pfn(pending_idx), ++ set_phys_to_machine(idx_to_pfn(netbk, pending_idx), + FOREIGN_FRAME(mop->dev_bus_addr>>PAGE_SHIFT)); +- grant_tx_handle[pending_idx] = mop->handle; ++ netbk->grant_tx_handle[pending_idx] = mop->handle; + /* Had a previous error? Invalidate this fragment. */ + if (unlikely(err)) +- netif_idx_release(pending_idx); ++ netif_idx_release(netbk, pending_idx); + continue; + } + + /* Error on this fragment: respond to client with an error. */ + txp = &pending_tx_info[pending_idx].req; + make_tx_response(netif, txp, NETIF_RSP_ERROR); +- pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx; ++ index = MASK_PEND_IDX(netbk->pending_prod++); ++ netbk->pending_ring[index] = pending_idx; + netif_put(netif); + + /* Not the first error? Preceding frags already invalidated. */ +@@ -1166,10 +1143,10 @@ static int netbk_tx_check_mop(struct sk_ + + /* First error: invalidate header and preceding fragments. */ + pending_idx = *((u16 *)skb->data); +- netif_idx_release(pending_idx); ++ netif_idx_release(netbk, pending_idx); + for (j = start; j < i; j++) { + pending_idx = (unsigned long)shinfo->frags[i].page; +- netif_idx_release(pending_idx); ++ netif_idx_release(netbk, pending_idx); + } + + /* Remember the error: invalidate all subsequent fragments. */ +@@ -1180,7 +1157,7 @@ static int netbk_tx_check_mop(struct sk_ + return err; + } + +-static void netbk_fill_frags(struct sk_buff *skb) ++static void netbk_fill_frags(struct xen_netbk *netbk, struct sk_buff *skb) + { + struct skb_shared_info *shinfo = skb_shinfo(skb); + int nr_frags = shinfo->nr_frags; +@@ -1193,12 +1170,12 @@ static void netbk_fill_frags(struct sk_b + + pending_idx = (unsigned long)frag->page; + +- pending_inuse[pending_idx].alloc_time = jiffies; +- list_add_tail(&pending_inuse[pending_idx].list, +- &pending_inuse_head); ++ netbk->pending_inuse[pending_idx].alloc_time = jiffies; ++ list_add_tail(&netbk->pending_inuse[pending_idx].list, ++ &netbk->pending_inuse_head); + +- txp = &pending_tx_info[pending_idx].req; +- frag->page = mmap_pages[pending_idx]; ++ txp = &netbk->pending_tx_info[pending_idx].req; ++ frag->page = netbk->mmap_pages[pending_idx]; + frag->size = txp->size; + frag->page_offset = txp->offset; + +@@ -1260,9 +1237,9 @@ static int netbk_set_skb_gso(struct sk_b + } + + /* Called after netfront has transmitted */ +-static void net_tx_action(unsigned long unused) ++static void net_tx_action(unsigned long group) + { +- struct list_head *ent; ++ struct xen_netbk *netbk = &xen_netbk[group]; + struct sk_buff *skb; + netif_t *netif; + netif_tx_request_t txreq; +@@ -1274,15 +1251,15 @@ static void net_tx_action(unsigned long + unsigned int data_len; + int ret, work_to_do; + +- net_tx_action_dealloc(); ++ net_tx_action_dealloc(netbk); + +- mop = tx_map_ops; ++ mop = netbk->tx_map_ops; + BUILD_BUG_ON(MAX_SKB_FRAGS >= MAX_PENDING_REQS); +- while (((NR_PENDING_REQS + MAX_SKB_FRAGS) < MAX_PENDING_REQS) && +- !list_empty(&net_schedule_list)) { ++ while (((nr_pending_reqs(netbk) + MAX_SKB_FRAGS) < MAX_PENDING_REQS) && ++ !list_empty(&netbk->net_schedule_list)) { + /* Get a netif from the list with work to do. */ +- ent = net_schedule_list.next; +- netif = list_entry(ent, netif_t, list); ++ netif = list_first_entry(&netbk->net_schedule_list, ++ netif_t, list); + netif_get(netif); + remove_from_net_schedule_list(netif); + +@@ -1364,7 +1341,7 @@ static void net_tx_action(unsigned long + continue; + } + +- pending_idx = pending_ring[MASK_PEND_IDX(pending_cons)]; ++ pending_idx = netbk->pending_ring[MASK_PEND_IDX(netbk->pending_cons)]; + + data_len = (txreq.size > PKT_PROT_LEN && + ret < MAX_SKB_FRAGS) ? +@@ -1392,14 +1369,14 @@ static void net_tx_action(unsigned long + } + } + +- gnttab_set_map_op(mop, idx_to_kaddr(pending_idx), ++ gnttab_set_map_op(mop, idx_to_kaddr(netbk, pending_idx), + GNTMAP_host_map | GNTMAP_readonly, + txreq.gref, netif->domid); + mop++; + +- memcpy(&pending_tx_info[pending_idx].req, ++ memcpy(&netbk->pending_tx_info[pending_idx].req, + &txreq, sizeof(txreq)); +- pending_tx_info[pending_idx].netif = netif; ++ netbk->pending_tx_info[pending_idx].netif = netif; + *((u16 *)skb->data) = pending_idx; + + __skb_put(skb, data_len); +@@ -1414,20 +1391,20 @@ static void net_tx_action(unsigned long + skb_shinfo(skb)->frags[0].page = (void *)~0UL; + } + +- __skb_queue_tail(&tx_queue, skb); ++ __skb_queue_tail(&netbk->tx_queue, skb); + +- pending_cons++; ++ netbk->pending_cons++; + + mop = netbk_get_requests(netif, skb, txfrags, mop); + + netif->tx.req_cons = i; + netif_schedule_work(netif); + +- if ((mop - tx_map_ops) >= ARRAY_SIZE(tx_map_ops)) ++ if ((mop - netbk->tx_map_ops) >= ARRAY_SIZE(netbk->tx_map_ops)) + break; + } + +- if (mop == tx_map_ops) ++ if (mop == netbk->tx_map_ops) + goto out; + + /* NOTE: some maps may fail with GNTST_eagain, which could be successfully +@@ -1435,20 +1412,21 @@ static void net_tx_action(unsigned long + * req and let the frontend resend the relevant packet again. This is fine + * because it is unlikely that a network buffer will be paged out or shared, + * and therefore it is unlikely to fail with GNTST_eagain. */ +- ret = HYPERVISOR_grant_table_op( +- GNTTABOP_map_grant_ref, tx_map_ops, mop - tx_map_ops); ++ ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, ++ netbk->tx_map_ops, ++ mop - netbk->tx_map_ops); + BUG_ON(ret); + +- mop = tx_map_ops; +- while ((skb = __skb_dequeue(&tx_queue)) != NULL) { ++ mop = netbk->tx_map_ops; ++ while ((skb = __skb_dequeue(&netbk->tx_queue)) != NULL) { + netif_tx_request_t *txp; + + pending_idx = *((u16 *)skb->data); +- netif = pending_tx_info[pending_idx].netif; +- txp = &pending_tx_info[pending_idx].req; ++ netif = netbk->pending_tx_info[pending_idx].netif; ++ txp = &netbk->pending_tx_info[pending_idx].req; + + /* Check the remap error code. */ +- if (unlikely(netbk_tx_check_mop(skb, &mop))) { ++ if (unlikely(netbk_tx_check_mop(netbk, skb, &mop))) { + DPRINTK("netback grant failed.\n"); + skb_shinfo(skb)->nr_frags = 0; + kfree_skb(skb); +@@ -1457,7 +1435,7 @@ static void net_tx_action(unsigned long + + data_len = skb->len; + memcpy(skb->data, +- (void *)(idx_to_kaddr(pending_idx)|txp->offset), ++ (void *)(idx_to_kaddr(netbk, pending_idx)|txp->offset), + data_len); + if (data_len < txp->size) { + /* Append the packet payload as a fragment. */ +@@ -1465,7 +1443,7 @@ static void net_tx_action(unsigned long + txp->size -= data_len; + } else { + /* Schedule a response immediately. */ +- netif_idx_release(pending_idx); ++ netif_idx_release(netbk, pending_idx); + } + + /* +@@ -1481,7 +1459,7 @@ static void net_tx_action(unsigned long + } + skb->proto_csum_blank = !!(txp->flags & NETTXF_csum_blank); + +- netbk_fill_frags(skb); ++ netbk_fill_frags(netbk, skb); + + skb->dev = netif->dev; + skb->protocol = eth_type_trans(skb, skb->dev); +@@ -1502,36 +1480,40 @@ static void net_tx_action(unsigned long + + out: + if (netbk_copy_skb_mode == NETBK_DELAYED_COPY_SKB && +- !list_empty(&pending_inuse_head)) { ++ !list_empty(&netbk->pending_inuse_head)) { + struct netbk_tx_pending_inuse *oldest; + +- oldest = list_entry(pending_inuse_head.next, ++ oldest = list_entry(netbk->pending_inuse_head.next, + struct netbk_tx_pending_inuse, list); +- mod_timer(&netbk_tx_pending_timer, oldest->alloc_time + HZ); ++ mod_timer(&netbk->tx_pending_timer, oldest->alloc_time + HZ); + } + } + +-static void netif_idx_release(u16 pending_idx) ++static void netif_idx_release(struct xen_netbk *netbk, u16 pending_idx) + { +- static DEFINE_SPINLOCK(_lock); + unsigned long flags; + +- spin_lock_irqsave(&_lock, flags); +- dealloc_ring[MASK_PEND_IDX(dealloc_prod)] = pending_idx; ++ spin_lock_irqsave(&netbk->release_lock, flags); ++ netbk->dealloc_ring[MASK_PEND_IDX(netbk->dealloc_prod)] = pending_idx; + /* Sync with net_tx_action_dealloc: insert idx /then/ incr producer. */ + smp_wmb(); +- dealloc_prod++; +- spin_unlock_irqrestore(&_lock, flags); ++ netbk->dealloc_prod++; ++ spin_unlock_irqrestore(&netbk->release_lock, flags); + +- tasklet_schedule(&net_tx_tasklet); ++ tasklet_schedule(&netbk->net_tx_tasklet); + } + + static void netif_page_release(struct page *page, unsigned int order) + { +- int idx = netif_page_index(page); ++ struct page_ext *ext = (void *)page->mapping; ++ unsigned int idx = ext->idx; ++ unsigned int group = ext->group; ++ struct xen_netbk *netbk = &xen_netbk[group]; ++ + BUG_ON(order); +- BUG_ON(idx < 0); +- netif_idx_release(idx); ++ BUG_ON(group >= netbk_nr_groups || idx >= MAX_PENDING_REQS); ++ BUG_ON(netbk->mmap_pages[idx] != page); ++ netif_idx_release(netbk, idx); + } + + irqreturn_t netif_be_int(int irq, void *dev_id) +@@ -1539,7 +1521,7 @@ irqreturn_t netif_be_int(int irq, void * + netif_t *netif = dev_id; + + add_to_net_schedule_list_tail(netif); +- maybe_schedule_tx_action(); ++ maybe_schedule_tx_action(GET_GROUP_INDEX(netif)); + + if (netif_schedulable(netif) && !netbk_queue_full(netif)) + netif_wake_queue(netif->dev); +@@ -1605,29 +1587,35 @@ static irqreturn_t netif_be_dbg(int irq, + { + struct list_head *ent; + netif_t *netif; +- int i = 0; ++ unsigned int i = 0, group; + + printk(KERN_ALERT "netif_schedule_list:\n"); +- spin_lock_irq(&net_schedule_list_lock); + +- list_for_each (ent, &net_schedule_list) { +- netif = list_entry(ent, netif_t, list); +- printk(KERN_ALERT " %d: private(rx_req_cons=%08x " +- "rx_resp_prod=%08x\n", +- i, netif->rx.req_cons, netif->rx.rsp_prod_pvt); +- printk(KERN_ALERT " tx_req_cons=%08x tx_resp_prod=%08x)\n", +- netif->tx.req_cons, netif->tx.rsp_prod_pvt); +- printk(KERN_ALERT " shared(rx_req_prod=%08x " +- "rx_resp_prod=%08x\n", +- netif->rx.sring->req_prod, netif->rx.sring->rsp_prod); +- printk(KERN_ALERT " rx_event=%08x tx_req_prod=%08x\n", +- netif->rx.sring->rsp_event, netif->tx.sring->req_prod); +- printk(KERN_ALERT " tx_resp_prod=%08x, tx_event=%08x)\n", +- netif->tx.sring->rsp_prod, netif->tx.sring->rsp_event); +- i++; ++ for (group = 0; group < netbk_nr_groups; ++group) { ++ struct xen_netbk *netbk = &xen_netbk[group]; ++ ++ spin_lock_irq(&netbk->net_schedule_list_lock); ++ ++ list_for_each(ent, &netbk->net_schedule_list) { ++ netif = list_entry(ent, netif_t, list); ++ printk(KERN_ALERT " %d: private(rx_req_cons=%08x " ++ "rx_resp_prod=%08x\n", ++ i, netif->rx.req_cons, netif->rx.rsp_prod_pvt); ++ printk(KERN_ALERT " tx_req_cons=%08x tx_resp_prod=%08x)\n", ++ netif->tx.req_cons, netif->tx.rsp_prod_pvt); ++ printk(KERN_ALERT " shared(rx_req_prod=%08x " ++ "rx_resp_prod=%08x\n", ++ netif->rx.sring->req_prod, netif->rx.sring->rsp_prod); ++ printk(KERN_ALERT " rx_event=%08x tx_req_prod=%08x\n", ++ netif->rx.sring->rsp_event, netif->tx.sring->req_prod); ++ printk(KERN_ALERT " tx_resp_prod=%08x, tx_event=%08x)\n", ++ netif->tx.sring->rsp_prod, netif->tx.sring->rsp_event); ++ i++; ++ } ++ ++ spin_unlock_irq(&netbk->netbk->net_schedule_list_lock); + } + +- spin_unlock_irq(&net_schedule_list_lock); + printk(KERN_ALERT " ** End of netif_schedule_list **\n"); + + return IRQ_HANDLED; +@@ -1642,7 +1630,8 @@ static struct irqaction netif_be_dbg_act + + static int __init netback_init(void) + { +- int i; ++ unsigned int i, group; ++ int rc; + struct page *page; + + if (!is_running_on_xen()) +@@ -1651,37 +1640,58 @@ static int __init netback_init(void) + /* We can increase reservation by this much in net_rx_action(). */ + balloon_update_driver_allowance(NET_RX_RING_SIZE); + +- skb_queue_head_init(&rx_queue); +- skb_queue_head_init(&tx_queue); +- +- init_timer(&net_timer); +- net_timer.data = 0; +- net_timer.function = net_alarm; +- +- init_timer(&netbk_tx_pending_timer); +- netbk_tx_pending_timer.data = 0; +- netbk_tx_pending_timer.function = netbk_tx_pending_timeout; +- +- mmap_pages = alloc_empty_pages_and_pagevec(MAX_PENDING_REQS); +- if (mmap_pages == NULL) { +- printk("%s: out of memory\n", __FUNCTION__); ++ xen_netbk = __vmalloc(netbk_nr_groups * sizeof(*xen_netbk), ++ GFP_KERNEL|__GFP_HIGHMEM|__GFP_ZERO, PAGE_KERNEL); ++ if (!xen_netbk) { ++ printk(KERN_ALERT "%s: out of memory\n", __func__); + return -ENOMEM; + } + +- for (i = 0; i < MAX_PENDING_REQS; i++) { +- page = mmap_pages[i]; +- SetPageForeign(page, netif_page_release); +- netif_set_page_index(page, i); +- INIT_LIST_HEAD(&pending_inuse[i].list); +- } ++ for (group = 0; group < netbk_nr_groups; group++) { ++ struct xen_netbk *netbk = &xen_netbk[group]; + +- pending_cons = 0; +- pending_prod = MAX_PENDING_REQS; +- for (i = 0; i < MAX_PENDING_REQS; i++) +- pending_ring[i] = i; ++ tasklet_init(&netbk->net_tx_tasklet, net_tx_action, group); ++ tasklet_init(&netbk->net_rx_tasklet, net_rx_action, group); + +- spin_lock_init(&net_schedule_list_lock); +- INIT_LIST_HEAD(&net_schedule_list); ++ skb_queue_head_init(&netbk->rx_queue); ++ skb_queue_head_init(&netbk->tx_queue); ++ ++ netbk->mmap_pages = ++ alloc_empty_pages_and_pagevec(MAX_PENDING_REQS); ++ if (netbk->mmap_pages == NULL) { ++ printk(KERN_ALERT "%s: out of memory\n", __func__); ++ rc = -ENOMEM; ++ goto failed_init; ++ } ++ ++ init_timer(&netbk->net_timer); ++ netbk->net_timer.data = group; ++ netbk->net_timer.function = net_alarm; ++ ++ init_timer(&netbk->tx_pending_timer); ++ netbk->tx_pending_timer.data = group; ++ netbk->tx_pending_timer.function = ++ netbk_tx_pending_timeout; ++ ++ netbk->pending_prod = MAX_PENDING_REQS; ++ ++ INIT_LIST_HEAD(&netbk->pending_inuse_head); ++ INIT_LIST_HEAD(&netbk->net_schedule_list); ++ ++ spin_lock_init(&netbk->net_schedule_list_lock); ++ spin_lock_init(&netbk->release_lock); ++ ++ for (i = 0; i < MAX_PENDING_REQS; i++) { ++ page = netbk->mmap_pages[i]; ++ SetPageForeign(page, netif_page_release); ++ netbk->page_extinfo[i].group = group; ++ netbk->page_extinfo[i].idx = i; ++ netif_set_page_ext(page, ++ &netbk->page_extinfo[i]); ++ netbk->pending_ring[i] = i; ++ INIT_LIST_HEAD(&netbk->pending_inuse[i].list); ++ } ++ } + + netbk_copy_skb_mode = NETBK_DONT_COPY_SKB; + if (MODPARM_copy_skb) { +@@ -1703,6 +1713,19 @@ static int __init netback_init(void) + #endif + + return 0; ++ ++failed_init: ++ while (group-- > 0) { ++ struct xen_netbk *netbk = &xen_netbk[group]; ++ ++ free_empty_pages_and_pagevec(netbk->mmap_pages, ++ MAX_PENDING_REQS); ++ del_timer(&netbk->tx_pending_timer); ++ del_timer(&netbk->net_timer); ++ } ++ vfree(xen_netbk); ++ ++ return rc; + } + + module_init(netback_init); diff --git a/xen-netback-kernel-threads b/xen-netback-kernel-threads new file mode 100644 index 0000000..acbe35e --- /dev/null +++ b/xen-netback-kernel-threads @@ -0,0 +1,285 @@ +From: Dongxiao Xu +Subject: [PATCH 3/3] Use Kernel thread to replace the tasklet. +Patch-mainline: n/a + + Kernel thread has more control over QoS, and could improve + dom0's userspace responseness. + +Signed-off-by: Dongxiao Xu + +Subject: xen: ensure locking gnttab_copy_grant_page is safe against interrupts. + +Now that netback processing occurs in a thread instead of a tasklet +gnttab_copy_grant_page needs to be safe against interrupts. + +The code is currently commented out in this tree but on 2.6.18 we observed a +deadlock where the netback thread called gnttab_copy_grant_page, locked +gnttab_dma_lock for writing, was interrupted and on return from interrupt the +network stack's TX tasklet ended up calling __gnttab_dma_map_page via the +hardware driver->swiotlb and tries to take gnttab_dma_lock for reading. + +Signed-off-by: Ian Campbell +Cc: Jeremy Fitzhardinge # +Cc: "Xu, Dongxiao" + +jb: changed write_seq{,un}lock_irq() to write_seq{,un}lock_bh(), and + made the use of kernel threads optional (but default) +Acked-by: jbeulich@novell.com + +--- sle11sp1-2010-03-05.orig/drivers/xen/core/gnttab.c 2009-12-15 09:28:00.000000000 +0100 ++++ sle11sp1-2010-03-05/drivers/xen/core/gnttab.c 2010-02-02 15:10:01.000000000 +0100 +@@ -553,14 +553,14 @@ int gnttab_copy_grant_page(grant_ref_t r + mfn = pfn_to_mfn(pfn); + new_mfn = virt_to_mfn(new_addr); + +- write_seqlock(&gnttab_dma_lock); ++ write_seqlock_bh(&gnttab_dma_lock); + + /* Make seq visible before checking page_mapped. */ + smp_mb(); + + /* Has the page been DMA-mapped? */ + if (unlikely(page_mapped(page))) { +- write_sequnlock(&gnttab_dma_lock); ++ write_sequnlock_bh(&gnttab_dma_lock); + put_page(new_page); + err = -EBUSY; + goto out; +@@ -577,7 +577,7 @@ int gnttab_copy_grant_page(grant_ref_t r + BUG_ON(err); + BUG_ON(unmap.status); + +- write_sequnlock(&gnttab_dma_lock); ++ write_sequnlock_bh(&gnttab_dma_lock); + + if (!xen_feature(XENFEAT_auto_translated_physmap)) { + set_phys_to_machine(page_to_pfn(new_page), INVALID_P2M_ENTRY); +--- sle11sp1-2010-03-05.orig/drivers/xen/netback/common.h 2010-01-14 08:40:17.000000000 +0100 ++++ sle11sp1-2010-03-05/drivers/xen/netback/common.h 2010-01-14 08:45:38.000000000 +0100 +@@ -245,8 +245,16 @@ struct netbk_tx_pending_inuse { + #define MAX_MFN_ALLOC 64 + + struct xen_netbk { +- struct tasklet_struct net_tx_tasklet; +- struct tasklet_struct net_rx_tasklet; ++ union { ++ struct { ++ struct tasklet_struct net_tx_tasklet; ++ struct tasklet_struct net_rx_tasklet; ++ }; ++ struct { ++ wait_queue_head_t netbk_action_wq; ++ struct task_struct *task; ++ }; ++ }; + + struct sk_buff_head rx_queue; + struct sk_buff_head tx_queue; +--- sle11sp1-2010-03-05.orig/drivers/xen/netback/netback.c 2010-03-08 10:54:19.000000000 +0100 ++++ sle11sp1-2010-03-05/drivers/xen/netback/netback.c 2010-03-08 10:56:45.000000000 +0100 +@@ -35,6 +35,7 @@ + */ + + #include "common.h" ++#include + #include + #include + #include +@@ -43,6 +44,8 @@ + + struct xen_netbk *xen_netbk; + unsigned int netbk_nr_groups; ++static bool use_kthreads = true; ++static bool __initdata bind_threads; + + #define GET_GROUP_INDEX(netif) ((netif)->group) + +@@ -94,7 +97,11 @@ static int MODPARM_permute_returns = 0; + module_param_named(permute_returns, MODPARM_permute_returns, bool, S_IRUSR|S_IWUSR); + MODULE_PARM_DESC(permute_returns, "Randomly permute the order in which TX responses are sent to the frontend"); + module_param_named(groups, netbk_nr_groups, uint, 0); +-MODULE_PARM_DESC(groups, "Specify the number of tasklet pairs to use"); ++MODULE_PARM_DESC(groups, "Specify the number of tasklet pairs/threads to use"); ++module_param_named(tasklets, use_kthreads, invbool, 0); ++MODULE_PARM_DESC(tasklets, "Use tasklets instead of kernel threads"); ++module_param_named(bind, bind_threads, bool, 0); ++MODULE_PARM_DESC(bind, "Bind kernel threads to (v)CPUs"); + + int netbk_copy_skb_mode; + +@@ -131,8 +138,12 @@ static inline void maybe_schedule_tx_act + + smp_mb(); + if ((nr_pending_reqs(netbk) < (MAX_PENDING_REQS/2)) && +- !list_empty(&netbk->net_schedule_list)) +- tasklet_schedule(&netbk->net_tx_tasklet); ++ !list_empty(&netbk->net_schedule_list)) { ++ if (use_kthreads) ++ wake_up(&netbk->netbk_action_wq); ++ else ++ tasklet_schedule(&netbk->net_tx_tasklet); ++ } + } + + static struct sk_buff *netbk_copy_skb(struct sk_buff *skb) +@@ -293,7 +304,10 @@ int netif_be_start_xmit(struct sk_buff * + + netbk = &xen_netbk[GET_GROUP_INDEX(netif)]; + skb_queue_tail(&netbk->rx_queue, skb); +- tasklet_schedule(&netbk->net_rx_tasklet); ++ if (use_kthreads) ++ wake_up(&netbk->netbk_action_wq); ++ else ++ tasklet_schedule(&netbk->net_rx_tasklet); + + return NETDEV_TX_OK; + +@@ -749,8 +763,12 @@ static void net_rx_action(unsigned long + + /* More work to do? */ + if (!skb_queue_empty(&netbk->rx_queue) && +- !timer_pending(&netbk->net_timer)) +- tasklet_schedule(&netbk->net_rx_tasklet); ++ !timer_pending(&netbk->net_timer)) { ++ if (use_kthreads) ++ wake_up(&netbk->netbk_action_wq); ++ else ++ tasklet_schedule(&netbk->net_rx_tasklet); ++ } + #if 0 + else + xen_network_done_notify(); +@@ -759,12 +777,18 @@ static void net_rx_action(unsigned long + + static void net_alarm(unsigned long group) + { +- tasklet_schedule(&xen_netbk[group].net_rx_tasklet); ++ if (use_kthreads) ++ wake_up(&xen_netbk[group].netbk_action_wq); ++ else ++ tasklet_schedule(&xen_netbk[group].net_rx_tasklet); + } + + static void netbk_tx_pending_timeout(unsigned long group) + { +- tasklet_schedule(&xen_netbk[group].net_tx_tasklet); ++ if (use_kthreads) ++ wake_up(&xen_netbk[group].netbk_action_wq); ++ else ++ tasklet_schedule(&xen_netbk[group].net_tx_tasklet); + } + + struct net_device_stats *netif_be_get_stats(struct net_device *dev) +@@ -1476,7 +1500,10 @@ static void net_tx_action(unsigned long + continue; + } + +- netif_rx(skb); ++ if (use_kthreads) ++ netif_rx_ni(skb); ++ else ++ netif_rx(skb); + netif->dev->last_rx = jiffies; + } + +@@ -1502,7 +1529,10 @@ static void netif_idx_release(struct xen + netbk->dealloc_prod++; + spin_unlock_irqrestore(&netbk->release_lock, flags); + +- tasklet_schedule(&netbk->net_tx_tasklet); ++ if (use_kthreads) ++ wake_up(&netbk->netbk_action_wq); ++ else ++ tasklet_schedule(&netbk->net_tx_tasklet); + } + + static void netif_page_release(struct page *page, unsigned int order) +@@ -1641,6 +1671,45 @@ static struct irqaction netif_be_dbg_act + }; + #endif + ++static inline int rx_work_todo(struct xen_netbk *netbk) ++{ ++ return !skb_queue_empty(&netbk->rx_queue); ++} ++ ++static inline int tx_work_todo(struct xen_netbk *netbk) ++{ ++ if (netbk->dealloc_cons != netbk->dealloc_prod) ++ return 1; ++ ++ if (nr_pending_reqs(netbk) + MAX_SKB_FRAGS < MAX_PENDING_REQS && ++ !list_empty(&netbk->net_schedule_list)) ++ return 1; ++ ++ return 0; ++} ++ ++static int netbk_action_thread(void *index) ++{ ++ unsigned long group = (unsigned long)index; ++ struct xen_netbk *netbk = &xen_netbk[group]; ++ ++ while (1) { ++ wait_event_interruptible(netbk->netbk_action_wq, ++ rx_work_todo(netbk) || ++ tx_work_todo(netbk)); ++ cond_resched(); ++ ++ if (rx_work_todo(netbk)) ++ net_rx_action(group); ++ ++ if (tx_work_todo(netbk)) ++ net_tx_action(group); ++ } ++ ++ return 0; ++} ++ ++ + static int __init netback_init(void) + { + unsigned int i, group; +@@ -1666,8 +1735,26 @@ static int __init netback_init(void) + for (group = 0; group < netbk_nr_groups; group++) { + struct xen_netbk *netbk = &xen_netbk[group]; + +- tasklet_init(&netbk->net_tx_tasklet, net_tx_action, group); +- tasklet_init(&netbk->net_rx_tasklet, net_rx_action, group); ++ if (use_kthreads) { ++ init_waitqueue_head(&netbk->netbk_action_wq); ++ netbk->task = kthread_create(netbk_action_thread, ++ (void *)(long)group, ++ "netback/%u", group); ++ ++ if (!IS_ERR(netbk->task)) { ++ if (bind_threads) ++ kthread_bind(netbk->task, group); ++ wake_up_process(netbk->task); ++ } else { ++ printk(KERN_ALERT ++ "kthread_create() fails at netback\n"); ++ rc = PTR_ERR(netbk->task); ++ goto failed_init; ++ } ++ } else { ++ tasklet_init(&netbk->net_tx_tasklet, net_tx_action, group); ++ tasklet_init(&netbk->net_rx_tasklet, net_rx_action, group); ++ } + + skb_queue_head_init(&netbk->rx_queue); + skb_queue_head_init(&netbk->tx_queue); +@@ -1736,8 +1823,11 @@ failed_init: + while (group-- > 0) { + struct xen_netbk *netbk = &xen_netbk[group]; + +- free_empty_pages_and_pagevec(netbk->mmap_pages, +- MAX_PENDING_REQS); ++ if (use_kthreads && netbk->task && !IS_ERR(netbk->task)) ++ kthread_stop(netbk->task); ++ if (netbk->mmap_pages) ++ free_empty_pages_and_pagevec(netbk->mmap_pages, ++ MAX_PENDING_REQS); + del_timer(&netbk->tx_pending_timer); + del_timer(&netbk->net_timer); + } diff --git a/xen-netback-multiple-tasklets b/xen-netback-multiple-tasklets new file mode 100644 index 0000000..ccf7e1d --- /dev/null +++ b/xen-netback-multiple-tasklets @@ -0,0 +1,185 @@ +From: Dongxiao Xu +Subject: [PATCH 2/3] Netback: Multiple tasklets support. +Patch-mainline: n/a + + Now netback uses one pair of tasklets for Tx/Rx data transaction. Netback + tasklet could only run at one CPU at a time, and it is used to serve all the + netfronts. Therefore it has become a performance bottle neck. This patch is to + use multiple tasklet pairs to replace the current single pair in dom0. + Assuming that Dom0 has CPUNR VCPUs, we define CPUNR kinds of tasklets pair + (CPUNR for Tx, and CPUNR for Rx). Each pare of tasklets serve specific group of + netfronts. Also for those global and static variables, we duplicated them for + each group in order to avoid the spinlock. + +Signed-off-by: Dongxiao Xu + +jb: some cleanups +Acked-by: jbeulich@novell.com + +--- sle11sp1-2010-03-05.orig/drivers/xen/netback/common.h 2010-01-14 08:39:00.000000000 +0100 ++++ sle11sp1-2010-03-05/drivers/xen/netback/common.h 2010-01-14 08:40:17.000000000 +0100 +@@ -58,6 +58,7 @@ + typedef struct netif_st { + /* Unique identifier for this interface. */ + domid_t domid; ++ unsigned int group; + unsigned int handle; + + u8 fe_dev_addr[6]; +@@ -99,6 +100,7 @@ typedef struct netif_st { + + /* Miscellaneous private stuff. */ + struct list_head list; /* scheduling list */ ++ struct list_head group_list; + atomic_t refcnt; + struct net_device *dev; + struct net_device_stats stats; +@@ -259,12 +261,15 @@ struct xen_netbk { + + struct list_head pending_inuse_head; + struct list_head net_schedule_list; ++ struct list_head group_domain_list; + + spinlock_t net_schedule_list_lock; + spinlock_t release_lock; ++ spinlock_t group_domain_list_lock; + + struct page **mmap_pages; + ++ unsigned int group_domain_nr; + unsigned int alloc_index; + + struct page_ext page_extinfo[MAX_PENDING_REQS]; +@@ -294,4 +299,8 @@ struct xen_netbk { + + unsigned long mfn_list[MAX_MFN_ALLOC]; + }; ++ ++extern struct xen_netbk *xen_netbk; ++extern unsigned int netbk_nr_groups; ++ + #endif /* __NETIF__BACKEND__COMMON_H__ */ +--- sle11sp1-2010-03-05.orig/drivers/xen/netback/interface.c 2010-01-04 13:31:46.000000000 +0100 ++++ sle11sp1-2010-03-05/drivers/xen/netback/interface.c 2010-03-05 10:35:22.000000000 +0100 +@@ -54,14 +54,41 @@ module_param_named(queue_length, netbk_q + + static void __netif_up(netif_t *netif) + { ++ unsigned int group = 0; ++ unsigned int min_domains = xen_netbk[0].group_domain_nr; ++ unsigned int i; ++ ++ /* Find the list which contains least number of domains. */ ++ for (i = 1; i < netbk_nr_groups; i++) { ++ if (xen_netbk[i].group_domain_nr < min_domains) { ++ group = i; ++ min_domains = xen_netbk[i].group_domain_nr; ++ } ++ } ++ ++ spin_lock(&xen_netbk[group].group_domain_list_lock); ++ list_add_tail(&netif->group_list, ++ &xen_netbk[group].group_domain_list); ++ xen_netbk[group].group_domain_nr++; ++ spin_unlock(&xen_netbk[group].group_domain_list_lock); ++ netif->group = group; ++ + enable_irq(netif->irq); + netif_schedule_work(netif); + } + + static void __netif_down(netif_t *netif) + { ++ struct xen_netbk *netbk = xen_netbk + netif->group; ++ + disable_irq(netif->irq); + netif_deschedule_work(netif); ++ ++ netif->group = UINT_MAX; ++ spin_lock(&netbk->group_domain_list_lock); ++ netbk->group_domain_nr--; ++ list_del(&netif->group_list); ++ spin_unlock(&netbk->group_domain_list_lock); + } + + static int net_open(struct net_device *dev) +@@ -203,6 +230,7 @@ netif_t *netif_alloc(struct device *pare + netif = netdev_priv(dev); + memset(netif, 0, sizeof(*netif)); + netif->domid = domid; ++ netif->group = UINT_MAX; + netif->handle = handle; + atomic_set(&netif->refcnt, 1); + init_waitqueue_head(&netif->waiting_to_free); +--- sle11sp1-2010-03-05.orig/drivers/xen/netback/netback.c 2010-01-29 12:51:48.000000000 +0100 ++++ sle11sp1-2010-03-05/drivers/xen/netback/netback.c 2010-03-08 10:54:19.000000000 +0100 +@@ -41,10 +41,10 @@ + + /*define NETBE_DEBUG_INTERRUPT*/ + +-static struct xen_netbk *xen_netbk; +-static unsigned int netbk_nr_groups = 1; ++struct xen_netbk *xen_netbk; ++unsigned int netbk_nr_groups; + +-#define GET_GROUP_INDEX(netif) (0) ++#define GET_GROUP_INDEX(netif) ((netif)->group) + + static void netif_idx_release(struct xen_netbk *, u16 pending_idx); + static void make_tx_response(netif_t *netif, +@@ -93,6 +93,8 @@ MODULE_PARM_DESC(copy_skb, "Copy data re + static int MODPARM_permute_returns = 0; + module_param_named(permute_returns, MODPARM_permute_returns, bool, S_IRUSR|S_IWUSR); + MODULE_PARM_DESC(permute_returns, "Randomly permute the order in which TX responses are sent to the frontend"); ++module_param_named(groups, netbk_nr_groups, uint, 0); ++MODULE_PARM_DESC(groups, "Specify the number of tasklet pairs to use"); + + int netbk_copy_skb_mode; + +@@ -1519,9 +1521,20 @@ static void netif_page_release(struct pa + irqreturn_t netif_be_int(int irq, void *dev_id) + { + netif_t *netif = dev_id; ++ unsigned int group = GET_GROUP_INDEX(netif); ++ ++ if (unlikely(group >= netbk_nr_groups)) { ++ /* ++ * Short of having a way to bind the IRQ in disabled mode ++ * (IRQ_NOAUTOEN), we have to ignore the first invocation(s) ++ * (before we got assigned to a group). ++ */ ++ BUG_ON(group != UINT_MAX); ++ return IRQ_HANDLED; ++ } + + add_to_net_schedule_list_tail(netif); +- maybe_schedule_tx_action(GET_GROUP_INDEX(netif)); ++ maybe_schedule_tx_action(group); + + if (netif_schedulable(netif) && !netbk_queue_full(netif)) + netif_wake_queue(netif->dev); +@@ -1637,8 +1650,11 @@ static int __init netback_init(void) + if (!is_running_on_xen()) + return -ENODEV; + ++ if (!netbk_nr_groups) ++ netbk_nr_groups = (num_online_cpus() + 1) / 2; ++ + /* We can increase reservation by this much in net_rx_action(). */ +- balloon_update_driver_allowance(NET_RX_RING_SIZE); ++ balloon_update_driver_allowance(netbk_nr_groups * NET_RX_RING_SIZE); + + xen_netbk = __vmalloc(netbk_nr_groups * sizeof(*xen_netbk), + GFP_KERNEL|__GFP_HIGHMEM|__GFP_ZERO, PAGE_KERNEL); +@@ -1677,9 +1693,11 @@ static int __init netback_init(void) + + INIT_LIST_HEAD(&netbk->pending_inuse_head); + INIT_LIST_HEAD(&netbk->net_schedule_list); ++ INIT_LIST_HEAD(&netbk->group_domain_list); + + spin_lock_init(&netbk->net_schedule_list_lock); + spin_lock_init(&netbk->release_lock); ++ spin_lock_init(&netbk->group_domain_list_lock); + + for (i = 0; i < MAX_PENDING_REQS; i++) { + page = netbk->mmap_pages[i]; diff --git a/xen-netback-notify-multi b/xen-netback-notify-multi new file mode 100644 index 0000000..191146b --- /dev/null +++ b/xen-netback-notify-multi @@ -0,0 +1,85 @@ +From: jbeulich@novell.com +Subject: netback: use multicall for send multiple notifications +Patch-mainline: obsolete + +This also does a small fairness improvement since now notifications +get sent in the order requests came in rather than in the inverse one. + +--- sle11sp1-2010-02-09.orig/drivers/xen/core/evtchn.c 2010-02-09 17:18:55.000000000 +0100 ++++ sle11sp1-2010-02-09/drivers/xen/core/evtchn.c 2010-02-09 17:19:07.000000000 +0100 +@@ -1335,6 +1335,21 @@ void notify_remote_via_irq(int irq) + } + EXPORT_SYMBOL_GPL(notify_remote_via_irq); + ++int multi_notify_remote_via_irq(multicall_entry_t *mcl, int irq) ++{ ++ int evtchn = evtchn_from_irq(irq); ++ ++ BUG_ON(type_from_irq(irq) == IRQT_VIRQ); ++ BUG_IF_IPI(irq); ++ ++ if (!VALID_EVTCHN(evtchn)) ++ return -EINVAL; ++ ++ multi_notify_remote_via_evtchn(mcl, evtchn); ++ return 0; ++} ++EXPORT_SYMBOL_GPL(multi_notify_remote_via_irq); ++ + int irq_to_evtchn_port(int irq) + { + BUG_IF_VIRQ_PER_CPU(irq); +--- sle11sp1-2010-02-09.orig/drivers/xen/netback/netback.c 2010-01-04 13:31:44.000000000 +0100 ++++ sle11sp1-2010-02-09/drivers/xen/netback/netback.c 2010-01-04 13:31:57.000000000 +0100 +@@ -778,10 +778,20 @@ static void net_rx_action(unsigned long + npo.meta_cons += nr_frags + 1; + } + +- while (notify_nr != 0) { +- irq = notify_list[--notify_nr]; ++ if (notify_nr == 1) { ++ irq = *notify_list; + __clear_bit(irq, rx_notify); + notify_remote_via_irq(irq + DYNIRQ_BASE); ++ } else { ++ for (count = ret = 0; ret < notify_nr; ++ret) { ++ irq = notify_list[ret]; ++ __clear_bit(irq, rx_notify); ++ if (!multi_notify_remote_via_irq(rx_mcl + count, ++ irq + DYNIRQ_BASE)) ++ ++count; ++ } ++ if (HYPERVISOR_multicall(rx_mcl, count)) ++ BUG(); + } + + /* More work to do? */ +--- sle11sp1-2010-02-09.orig/include/xen/evtchn.h 2009-12-18 10:13:32.000000000 +0100 ++++ sle11sp1-2010-02-09/include/xen/evtchn.h 2009-12-18 10:13:40.000000000 +0100 +@@ -193,6 +193,18 @@ static inline void notify_remote_via_evt + VOID(HYPERVISOR_event_channel_op(EVTCHNOP_send, &send)); + } + ++static inline void ++multi_notify_remote_via_evtchn(multicall_entry_t *mcl, int port) ++{ ++ struct evtchn_send *send = (void *)(mcl->args + 2); ++ ++ BUILD_BUG_ON(sizeof(*send) > sizeof(mcl->args) - 2 * sizeof(*mcl->args)); ++ send->port = port; ++ mcl->op = __HYPERVISOR_event_channel_op; ++ mcl->args[0] = EVTCHNOP_send; ++ mcl->args[1] = (unsigned long)send; ++} ++ + /* Clear an irq's pending state, in preparation for polling on it. */ + void xen_clear_irq_pending(int irq); + +@@ -211,6 +223,7 @@ void xen_poll_irq(int irq); + * by bind_*_to_irqhandler(). + */ + void notify_remote_via_irq(int irq); ++int multi_notify_remote_via_irq(multicall_entry_t *, int irq); + int irq_to_evtchn_port(int irq); + + #if defined(CONFIG_SMP) && !defined(MODULE) && defined(CONFIG_X86) diff --git a/xen-netback-nr-irqs b/xen-netback-nr-irqs new file mode 100644 index 0000000..cf48865 --- /dev/null +++ b/xen-netback-nr-irqs @@ -0,0 +1,61 @@ +From: jbeulich@novell.com +Subject: netback: reduce overhead of IRQ recording +Patch-mainline: obsolete + +Since both NR_PIRQS and NR_DYNIRQS are no longer hardcoded, the +(memory) overhead of tracking which ones to send notifications to can +be pretty unbounded. Also, store the dynirq rather than the raw irq +to push up the limit where the type of notify_list needs to become +'int' rather than 'u16'. + +--- head-2010-01-04.orig/drivers/xen/netback/interface.c 2010-01-04 12:42:38.000000000 +0100 ++++ head-2010-01-04/drivers/xen/netback/interface.c 2010-01-04 13:31:46.000000000 +0100 +@@ -339,6 +339,7 @@ int netif_map(netif_t *netif, unsigned l + netif->dev->name, netif); + if (err < 0) + goto err_hypervisor; ++ BUG_ON(err < DYNIRQ_BASE || err >= DYNIRQ_BASE + NR_DYNIRQS); + netif->irq = err; + disable_irq(netif->irq); + +--- head-2010-01-04.orig/drivers/xen/netback/netback.c 2010-01-04 13:31:38.000000000 +0100 ++++ head-2010-01-04/drivers/xen/netback/netback.c 2010-01-04 13:31:44.000000000 +0100 +@@ -590,8 +590,12 @@ static void net_rx_action(unsigned long + static mmu_update_t rx_mmu[NET_RX_RING_SIZE]; + static gnttab_transfer_t grant_trans_op[NET_RX_RING_SIZE]; + static gnttab_copy_t grant_copy_op[NET_RX_RING_SIZE]; +- static unsigned char rx_notify[NR_IRQS]; ++ static DECLARE_BITMAP(rx_notify, NR_DYNIRQS); ++#if NR_DYNIRQS <= 0x10000 + static u16 notify_list[NET_RX_RING_SIZE]; ++#else ++ static int notify_list[NET_RX_RING_SIZE]; ++#endif + static struct netbk_rx_meta meta[NET_RX_RING_SIZE]; + + struct netrx_pending_operations npo = { +@@ -749,11 +753,9 @@ static void net_rx_action(unsigned long + nr_frags); + + RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&netif->rx, ret); +- irq = netif->irq; +- if (ret && !rx_notify[irq]) { +- rx_notify[irq] = 1; ++ irq = netif->irq - DYNIRQ_BASE; ++ if (ret && !__test_and_set_bit(irq, rx_notify)) + notify_list[notify_nr++] = irq; +- } + + if (netif_queue_stopped(netif->dev) && + netif_schedulable(netif) && +@@ -778,8 +780,8 @@ static void net_rx_action(unsigned long + + while (notify_nr != 0) { + irq = notify_list[--notify_nr]; +- rx_notify[irq] = 0; +- notify_remote_via_irq(irq); ++ __clear_bit(irq, rx_notify); ++ notify_remote_via_irq(irq + DYNIRQ_BASE); + } + + /* More work to do? */ diff --git a/xen-netfront-ethtool b/xen-netfront-ethtool new file mode 100644 index 0000000..1eddafe --- /dev/null +++ b/xen-netfront-ethtool @@ -0,0 +1,31 @@ +From: ksrinivasan@novell.com +Subject: netfront: ethtool -i does not return info about xennet driver +Patch-mainline: n/a +References: bnc#591179 + +Signed-off-by: K. Y. Srinivasan + +--- sle11sp1-2010-03-29.orig/drivers/xen/netfront/netfront.c 2009-11-06 10:52:23.000000000 +0100 ++++ sle11sp1-2010-03-29/drivers/xen/netfront/netfront.c 2010-03-27 00:18:30.000000000 +0100 +@@ -1766,6 +1766,13 @@ static void xennet_set_features(struct n + xennet_set_tso(dev, 1); + } + ++static void netfront_get_drvinfo(struct net_device *dev, ++ struct ethtool_drvinfo *info) ++{ ++ strcpy(info->driver, "netfront"); ++ strcpy(info->bus_info, dev_name(dev->dev.parent)); ++} ++ + static int network_connect(struct net_device *dev) + { + struct netfront_info *np = netdev_priv(dev); +@@ -1874,6 +1881,7 @@ static void netif_uninit(struct net_devi + + static const struct ethtool_ops network_ethtool_ops = + { ++ .get_drvinfo = netfront_get_drvinfo, + .get_tx_csum = ethtool_op_get_tx_csum, + .set_tx_csum = ethtool_op_set_tx_csum, + .get_sg = ethtool_op_get_sg, diff --git a/xen-op-packet b/xen-op-packet new file mode 100644 index 0000000..87bbf15 --- /dev/null +++ b/xen-op-packet @@ -0,0 +1,190 @@ +From: plc@novell.com +Subject: add support for new operation type BLKIF_OP_PACKET +Patch-mainline: obsolete +References: fate#300964 + +--- sle11sp1-2010-03-22.orig/drivers/xen/blkback/blkback.c 2010-03-22 12:26:12.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/xen/blkback/blkback.c 2010-03-22 12:57:07.000000000 +0100 +@@ -195,13 +195,15 @@ static void fast_flush_area(pending_req_ + + static void print_stats(blkif_t *blkif) + { +- printk(KERN_DEBUG "%s: oo %3d | rd %4d | wr %4d | br %4d\n", ++ printk(KERN_DEBUG "%s: oo %3d | rd %4d | wr %4d | br %4d | pk %4d\n", + current->comm, blkif->st_oo_req, +- blkif->st_rd_req, blkif->st_wr_req, blkif->st_br_req); ++ blkif->st_rd_req, blkif->st_wr_req, blkif->st_br_req, ++ blkif->st_pk_req); + blkif->st_print = jiffies + msecs_to_jiffies(10 * 1000); + blkif->st_rd_req = 0; + blkif->st_wr_req = 0; + blkif->st_oo_req = 0; ++ blkif->st_pk_req = 0; + } + + int blkif_schedule(void *arg) +@@ -374,6 +376,13 @@ handle_request: + blkif->st_wr_req++; + ret = dispatch_rw_block_io(blkif, &req, pending_req); + break; ++ case BLKIF_OP_PACKET: ++ DPRINTK("error: block operation BLKIF_OP_PACKET not implemented\n"); ++ blkif->st_pk_req++; ++ make_response(blkif, req.id, req.operation, ++ BLKIF_RSP_ERROR); ++ free_req(pending_req); ++ break; + default: + /* A good sign something is wrong: sleep for a while to + * avoid excessive CPU consumption by a bad guest. */ +--- sle11sp1-2010-03-22.orig/drivers/xen/blkback/common.h 2010-03-22 12:54:11.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/xen/blkback/common.h 2010-03-22 12:57:06.000000000 +0100 +@@ -92,6 +92,7 @@ typedef struct blkif_st { + int st_wr_req; + int st_oo_req; + int st_br_req; ++ int st_pk_req; + int st_rd_sect; + int st_wr_sect; + +--- sle11sp1-2010-03-22.orig/drivers/xen/blkfront/blkfront.c 2010-03-22 12:26:04.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/xen/blkfront/blkfront.c 2010-03-22 12:57:12.000000000 +0100 +@@ -671,6 +671,8 @@ static int blkif_queue_request(struct re + BLKIF_OP_WRITE : BLKIF_OP_READ; + if (blk_barrier_rq(req)) + ring_req->operation = BLKIF_OP_WRITE_BARRIER; ++ if (blk_pc_request(req)) ++ ring_req->operation = BLKIF_OP_PACKET; + + ring_req->nr_segments = blk_rq_map_sg(req->q, req, info->sg); + BUG_ON(ring_req->nr_segments > BLKIF_MAX_SEGMENTS_PER_REQUEST); +@@ -728,7 +730,7 @@ void do_blkif_request(struct request_que + + blk_start_request(req); + +- if (!blk_fs_request(req)) { ++ if (!blk_fs_request(req) && !blk_pc_request(req)) { + __blk_end_request_all(req, -EIO); + continue; + } +@@ -799,6 +801,7 @@ static irqreturn_t blkif_int(int irq, vo + /* fall through */ + case BLKIF_OP_READ: + case BLKIF_OP_WRITE: ++ case BLKIF_OP_PACKET: + if (unlikely(bret->status != BLKIF_RSP_OKAY)) + DPRINTK("Bad return from blkdev data " + "request: %x\n", bret->status); +--- sle11sp1-2010-03-22.orig/drivers/xen/blktap/blktap.c 2010-01-04 13:22:24.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/xen/blktap/blktap.c 2010-01-04 13:22:46.000000000 +0100 +@@ -1134,13 +1134,14 @@ static void fast_flush_area(pending_req_ + + static void print_stats(blkif_t *blkif) + { +- printk(KERN_DEBUG "%s: oo %3d | rd %4d | wr %4d\n", ++ printk(KERN_DEBUG "%s: oo %3d | rd %4d | wr %4d | pk %4d\n", + current->comm, blkif->st_oo_req, +- blkif->st_rd_req, blkif->st_wr_req); ++ blkif->st_rd_req, blkif->st_wr_req, blkif->st_pk_req); + blkif->st_print = jiffies + msecs_to_jiffies(10 * 1000); + blkif->st_rd_req = 0; + blkif->st_wr_req = 0; + blkif->st_oo_req = 0; ++ blkif->st_pk_req = 0; + } + + int tap_blkif_schedule(void *arg) +@@ -1374,6 +1375,11 @@ static int do_block_io_op(blkif_t *blkif + dispatch_rw_block_io(blkif, &req, pending_req); + break; + ++ case BLKIF_OP_PACKET: ++ blkif->st_pk_req++; ++ dispatch_rw_block_io(blkif, &req, pending_req); ++ break; ++ + default: + /* A good sign something is wrong: sleep for a while to + * avoid excessive CPU consumption by a bad guest. */ +@@ -1413,6 +1419,8 @@ static void dispatch_rw_block_io(blkif_t + struct vm_area_struct *vma = NULL; + + switch (req->operation) { ++ case BLKIF_OP_PACKET: ++ /* Fall through */ + case BLKIF_OP_READ: + operation = READ; + break; +--- sle11sp1-2010-03-22.orig/drivers/xen/blktap/common.h 2009-11-06 10:51:07.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/xen/blktap/common.h 2009-07-29 10:18:11.000000000 +0200 +@@ -75,6 +75,7 @@ typedef struct blkif_st { + int st_rd_req; + int st_wr_req; + int st_oo_req; ++ int st_pk_req; + int st_rd_sect; + int st_wr_sect; + +--- sle11sp1-2010-03-22.orig/drivers/xen/blktap2/blktap.h 2009-12-16 11:51:26.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/xen/blktap2/blktap.h 2009-12-16 12:14:37.000000000 +0100 +@@ -137,6 +137,7 @@ struct blktap_statistics { + int st_rd_req; + int st_wr_req; + int st_oo_req; ++ int st_pk_req; + int st_rd_sect; + int st_wr_sect; + s64 st_rd_cnt; +--- sle11sp1-2010-03-22.orig/drivers/xen/blktap2/device.c 2009-11-06 10:52:23.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/xen/blktap2/device.c 2010-01-04 13:22:52.000000000 +0100 +@@ -369,7 +369,8 @@ blktap_device_fail_pending_requests(stru + + BTERR("%u:%u: failing pending %s of %d pages\n", + blktap_device_major, tap->minor, +- (request->operation == BLKIF_OP_READ ? ++ (request->operation == BLKIF_OP_PACKET ? ++ "packet" : request->operation == BLKIF_OP_READ ? + "read" : "write"), request->nr_pages); + + blktap_unmap(tap, request); +@@ -410,6 +411,7 @@ blktap_device_finish_request(struct blkt + switch (request->operation) { + case BLKIF_OP_READ: + case BLKIF_OP_WRITE: ++ case BLKIF_OP_PACKET: + if (unlikely(res->status != BLKIF_RSP_OKAY)) + BTERR("Bad return from device data " + "request: %x\n", res->status); +@@ -648,6 +650,8 @@ blktap_device_process_request(struct blk + blkif_req.handle = 0; + blkif_req.operation = rq_data_dir(req) ? + BLKIF_OP_WRITE : BLKIF_OP_READ; ++ if (unlikely(blk_pc_request(req))) ++ blkif_req.operation = BLKIF_OP_PACKET; + + request->id = (unsigned long)req; + request->operation = blkif_req.operation; +@@ -713,7 +717,9 @@ blktap_device_process_request(struct blk + wmb(); /* blktap_poll() reads req_prod_pvt asynchronously */ + ring->ring.req_prod_pvt++; + +- if (rq_data_dir(req)) { ++ if (unlikely(blk_pc_request(req))) ++ tap->stats.st_pk_req++; ++ else if (rq_data_dir(req)) { + tap->stats.st_wr_sect += nr_sects; + tap->stats.st_wr_req++; + } else { +--- sle11sp1-2010-03-22.orig/include/xen/interface/io/blkif.h 2009-12-04 10:44:50.000000000 +0100 ++++ sle11sp1-2010-03-22/include/xen/interface/io/blkif.h 2009-07-29 10:18:11.000000000 +0200 +@@ -76,6 +76,10 @@ + * "feature-flush-cache" node! + */ + #define BLKIF_OP_FLUSH_DISKCACHE 3 ++/* ++ * Device specific command packet contained within the request ++ */ ++#define BLKIF_OP_PACKET 4 + + /* + * Maximum scatter/gather segments per request. diff --git a/xen-sections b/xen-sections new file mode 100644 index 0000000..5a1ffdb --- /dev/null +++ b/xen-sections @@ -0,0 +1,127 @@ +From: jbeulich@novell.com +Subject: fix placement of some routines/data +Patch-mainline: obsolete + +--- sle11sp1-2010-03-22.orig/arch/x86/kernel/time-xen.c 2010-02-09 17:07:46.000000000 +0100 ++++ sle11sp1-2010-03-22/arch/x86/kernel/time-xen.c 2010-03-01 14:45:54.000000000 +0100 +@@ -674,7 +674,7 @@ int xen_update_persistent_clock(void) + /* Dynamically-mapped IRQ. */ + DEFINE_PER_CPU(int, timer_irq); + +-static void setup_cpu0_timer_irq(void) ++static void __init setup_cpu0_timer_irq(void) + { + per_cpu(timer_irq, 0) = + bind_virq_to_irqhandler( +@@ -899,7 +899,7 @@ int __cpuinit local_setup_timer(unsigned + return 0; + } + +-void __cpuexit local_teardown_timer(unsigned int cpu) ++void __cpuinit local_teardown_timer(unsigned int cpu) + { + BUG_ON(cpu == 0); + unbind_from_irqhandler(per_cpu(timer_irq, cpu), NULL); +--- sle11sp1-2010-03-22.orig/drivers/xen/core/cpu_hotplug.c 2009-11-06 10:51:55.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/xen/core/cpu_hotplug.c 2009-11-06 11:09:19.000000000 +0100 +@@ -24,7 +24,7 @@ static int local_cpu_hotplug_request(voi + return (current->mm != NULL); + } + +-static void vcpu_hotplug(unsigned int cpu) ++static void __cpuinit vcpu_hotplug(unsigned int cpu) + { + int err; + char dir[32], state[32]; +@@ -51,7 +51,7 @@ static void vcpu_hotplug(unsigned int cp + } + } + +-static void handle_vcpu_hotplug_event( ++static void __cpuinit handle_vcpu_hotplug_event( + struct xenbus_watch *watch, const char **vec, unsigned int len) + { + unsigned int cpu; +@@ -80,12 +80,12 @@ static int smpboot_cpu_notify(struct not + return NOTIFY_OK; + } + +-static int setup_cpu_watcher(struct notifier_block *notifier, +- unsigned long event, void *data) ++static int __cpuinit setup_cpu_watcher(struct notifier_block *notifier, ++ unsigned long event, void *data) + { + unsigned int i; + +- static struct xenbus_watch cpu_watch = { ++ static struct xenbus_watch __cpuinitdata cpu_watch = { + .node = "cpu", + .callback = handle_vcpu_hotplug_event, + .flags = XBWF_new_thread }; +@@ -105,7 +105,7 @@ static int __init setup_vcpu_hotplug_eve + { + static struct notifier_block hotplug_cpu = { + .notifier_call = smpboot_cpu_notify }; +- static struct notifier_block xsn_cpu = { ++ static struct notifier_block __cpuinitdata xsn_cpu = { + .notifier_call = setup_cpu_watcher }; + + if (!is_running_on_xen()) +@@ -119,7 +119,7 @@ static int __init setup_vcpu_hotplug_eve + + arch_initcall(setup_vcpu_hotplug_event); + +-int smp_suspend(void) ++int __ref smp_suspend(void) + { + unsigned int cpu; + int err; +@@ -140,7 +140,7 @@ int smp_suspend(void) + return 0; + } + +-void smp_resume(void) ++void __ref smp_resume(void) + { + unsigned int cpu; + +--- sle11sp1-2010-03-22.orig/drivers/xen/core/smpboot.c 2010-03-22 12:25:59.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/xen/core/smpboot.c 2010-03-22 12:57:24.000000000 +0100 +@@ -181,7 +181,7 @@ static int __cpuinit xen_smp_intr_init(u + } + + #ifdef CONFIG_HOTPLUG_CPU +-static void __cpuexit xen_smp_intr_exit(unsigned int cpu) ++static void __cpuinit xen_smp_intr_exit(unsigned int cpu) + { + if (cpu != 0) + local_teardown_timer(cpu); +@@ -400,7 +400,7 @@ int __cpuexit __cpu_disable(void) + return 0; + } + +-void __cpuexit __cpu_die(unsigned int cpu) ++void __cpuinit __cpu_die(unsigned int cpu) + { + while (HYPERVISOR_vcpu_op(VCPUOP_is_up, cpu, NULL)) { + current->state = TASK_UNINTERRUPTIBLE; +--- sle11sp1-2010-03-22.orig/drivers/xen/evtchn/evtchn.c 2009-03-18 10:39:31.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/xen/evtchn/evtchn.c 2009-11-06 11:09:19.000000000 +0100 +@@ -549,14 +549,15 @@ static int __init evtchn_init(void) + + return 0; + } ++module_init(evtchn_init); + ++#ifdef CONFIG_MODULE + static void __exit evtchn_cleanup(void) + { + misc_deregister(&evtchn_miscdev); + unregister_cpu_notifier(&evtchn_cpu_nfb); + } +- +-module_init(evtchn_init); + module_exit(evtchn_cleanup); ++#endif + + MODULE_LICENSE("Dual BSD/GPL"); diff --git a/xen-spinlock-poll-early b/xen-spinlock-poll-early new file mode 100644 index 0000000..433d526 --- /dev/null +++ b/xen-spinlock-poll-early @@ -0,0 +1,177 @@ +From: jbeulich@novell.com +Subject: Go into polling mode early if lock owner is not running +Patch-mainline: n/a + +This could be merged into the original ticket spinlock code once +validated, if there wasn't the dependency on smp-processor-id.h, which +only gets introduced in the 2.6.32 merge. + +--- sle11sp1-2010-03-22.orig/arch/x86/include/mach-xen/asm/spinlock.h 2010-02-23 14:24:59.000000000 +0100 ++++ sle11sp1-2010-03-22/arch/x86/include/mach-xen/asm/spinlock.h 2010-02-23 14:28:29.000000000 +0100 +@@ -41,6 +41,10 @@ + #ifdef TICKET_SHIFT + + #include ++#include ++#include ++ ++DECLARE_PER_CPU(struct vcpu_runstate_info, runstate); + + int xen_spinlock_init(unsigned int cpu); + void xen_spinlock_cleanup(unsigned int cpu); +@@ -113,6 +117,9 @@ static __always_inline int __ticket_spin + : + : "memory", "cc"); + ++ if (tmp) ++ lock->owner = raw_smp_processor_id(); ++ + return tmp; + } + #elif TICKET_SHIFT == 16 +@@ -179,10 +186,17 @@ static __always_inline int __ticket_spin + : + : "memory", "cc"); + ++ if (tmp) ++ lock->owner = raw_smp_processor_id(); ++ + return tmp; + } + #endif + ++#define __ticket_spin_count(lock) \ ++ (per_cpu(runstate.state, (lock)->owner) == RUNSTATE_running \ ++ ? 1 << 10 : 1) ++ + static inline int __ticket_spin_is_locked(raw_spinlock_t *lock) + { + int tmp = ACCESS_ONCE(lock->slock); +@@ -204,16 +218,18 @@ static __always_inline void __ticket_spi + bool free; + + __ticket_spin_lock_preamble; +- if (likely(free)) { ++ if (likely(free)) ++ raw_local_irq_restore(flags); ++ else { ++ token = xen_spin_adjust(lock, token); + raw_local_irq_restore(flags); +- return; ++ do { ++ count = __ticket_spin_count(lock); ++ __ticket_spin_lock_body; ++ } while (unlikely(!count) ++ && !xen_spin_wait(lock, &token, flags)); + } +- token = xen_spin_adjust(lock, token); +- raw_local_irq_restore(flags); +- do { +- count = 1 << 10; +- __ticket_spin_lock_body; +- } while (unlikely(!count) && !xen_spin_wait(lock, &token, flags)); ++ lock->owner = raw_smp_processor_id(); + } + + static __always_inline void __ticket_spin_lock_flags(raw_spinlock_t *lock, +@@ -223,13 +239,15 @@ static __always_inline void __ticket_spi + bool free; + + __ticket_spin_lock_preamble; +- if (likely(free)) +- return; +- token = xen_spin_adjust(lock, token); +- do { +- count = 1 << 10; +- __ticket_spin_lock_body; +- } while (unlikely(!count) && !xen_spin_wait(lock, &token, flags)); ++ if (unlikely(!free)) { ++ token = xen_spin_adjust(lock, token); ++ do { ++ count = __ticket_spin_count(lock); ++ __ticket_spin_lock_body; ++ } while (unlikely(!count) ++ && !xen_spin_wait(lock, &token, flags)); ++ } ++ lock->owner = raw_smp_processor_id(); + } + + static __always_inline void __ticket_spin_unlock(raw_spinlock_t *lock) +@@ -246,6 +264,7 @@ static __always_inline void __ticket_spi + #undef __ticket_spin_lock_preamble + #undef __ticket_spin_lock_body + #undef __ticket_spin_unlock_body ++#undef __ticket_spin_count + #endif + + #define __raw_spin(n) __ticket_spin_##n +--- sle11sp1-2010-03-22.orig/arch/x86/include/mach-xen/asm/spinlock_types.h 2010-01-18 16:52:32.000000000 +0100 ++++ sle11sp1-2010-03-22/arch/x86/include/mach-xen/asm/spinlock_types.h 2010-01-26 09:48:51.000000000 +0100 +@@ -24,6 +24,11 @@ typedef union { + # define TICKET_SHIFT 16 + u16 cur, seq; + #endif ++#if CONFIG_NR_CPUS <= 256 ++ u8 owner; ++#else ++ u16 owner; ++#endif + #else + /* + * This differs from the pre-2.6.24 spinlock by always using xchgb +--- sle11sp1-2010-03-22.orig/arch/x86/kernel/time-xen.c 2010-03-01 14:46:13.000000000 +0100 ++++ sle11sp1-2010-03-22/arch/x86/kernel/time-xen.c 2010-02-04 09:43:52.000000000 +0100 +@@ -64,7 +64,7 @@ static DEFINE_PER_CPU(u64, processed_sto + static DEFINE_PER_CPU(u64, processed_blocked_time); + + /* Current runstate of each CPU (updated automatically by the hypervisor). */ +-static DEFINE_PER_CPU(struct vcpu_runstate_info, runstate); ++DEFINE_PER_CPU(struct vcpu_runstate_info, runstate); + + /* Must be signed, as it's compared with s64 quantities which can be -ve. */ + #define NS_PER_TICK (1000000000LL/HZ) +--- sle11sp1-2010-03-22.orig/drivers/xen/core/spinlock.c 2010-02-23 12:31:40.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/xen/core/spinlock.c 2010-03-22 12:58:39.000000000 +0100 +@@ -38,6 +38,8 @@ int __cpuinit xen_spinlock_init(unsigned + }; + int rc; + ++ setup_runstate_area(cpu); ++ + rc = bind_ipi_to_irqaction(SPIN_UNLOCK_VECTOR, + cpu, + &spinlock_action); +@@ -85,6 +87,7 @@ unsigned int xen_spin_adjust(const raw_s + bool xen_spin_wait(raw_spinlock_t *lock, unsigned int *ptok, + unsigned int flags) + { ++ unsigned int cpu = raw_smp_processor_id(); + int irq = spinlock_irq; + bool rc; + typeof(vcpu_info(0)->evtchn_upcall_mask) upcall_mask; +@@ -92,7 +95,7 @@ bool xen_spin_wait(raw_spinlock_t *lock, + struct spinning spinning, *other; + + /* If kicker interrupt not initialized yet, just spin. */ +- if (unlikely(irq < 0) || unlikely(!cpu_online(raw_smp_processor_id()))) ++ if (unlikely(irq < 0) || unlikely(!cpu_online(cpu))) + return false; + + /* announce we're spinning */ +@@ -113,6 +116,7 @@ bool xen_spin_wait(raw_spinlock_t *lock, + * we weren't looking. + */ + if (lock->cur == spinning.ticket) { ++ lock->owner = cpu; + /* + * If we interrupted another spinlock while it was + * blocking, make sure it doesn't block (again) +@@ -206,6 +210,8 @@ bool xen_spin_wait(raw_spinlock_t *lock, + if (!free) + token = spin_adjust(other->prev, lock, token); + other->ticket = token >> TICKET_SHIFT; ++ if (lock->cur == other->ticket) ++ lock->owner = cpu; + } + raw_local_irq_restore(upcall_mask); + diff --git a/xen-staging-build b/xen-staging-build new file mode 100644 index 0000000..983c5e4 --- /dev/null +++ b/xen-staging-build @@ -0,0 +1,40 @@ +From: jbeulich@novell.com +Subject: fix issue with Windows-style types used in drivers/staging/ +Patch-mainline: obsolete + +--- head-2009-11-20.orig/arch/x86/include/mach-xen/asm/hypervisor.h 2009-11-23 10:44:04.000000000 +0100 ++++ head-2009-11-20/arch/x86/include/mach-xen/asm/hypervisor.h 2009-11-23 10:45:08.000000000 +0100 +@@ -354,4 +354,9 @@ MULTI_grant_table_op(multicall_entry_t * + + #define uvm_multi(cpumask) ((unsigned long)cpumask_bits(cpumask) | UVMF_MULTI) + ++#ifdef LINUX ++/* drivers/staging/ use Windows-style types, including VOID */ ++#undef VOID ++#endif ++ + #endif /* __HYPERVISOR_H__ */ +--- head-2009-11-20.orig/drivers/staging/vt6655/ttype.h 2009-11-23 10:15:03.000000000 +0100 ++++ head-2009-11-20/drivers/staging/vt6655/ttype.h 2009-10-13 17:02:12.000000000 +0200 +@@ -30,6 +30,9 @@ + #ifndef __TTYPE_H__ + #define __TTYPE_H__ + ++#ifdef CONFIG_XEN ++#include ++#endif + + /******* Common definitions and typedefs ***********************************/ + +--- head-2009-11-20.orig/drivers/staging/vt6656/ttype.h 2009-11-23 10:15:03.000000000 +0100 ++++ head-2009-11-20/drivers/staging/vt6656/ttype.h 2009-10-13 17:02:12.000000000 +0200 +@@ -30,6 +30,9 @@ + #ifndef __TTYPE_H__ + #define __TTYPE_H__ + ++#ifdef CONFIG_XEN ++#include ++#endif + + /******* Common definitions and typedefs ***********************************/ + diff --git a/xen-swiotlb-heuristics b/xen-swiotlb-heuristics new file mode 100644 index 0000000..38768c3 --- /dev/null +++ b/xen-swiotlb-heuristics @@ -0,0 +1,32 @@ +From: jbeulich@novell.com +Subject: adjust Xen's swiotlb default size setting +Patch-mainline: obsolete + +--- head-2009-10-12.orig/lib/swiotlb-xen.c 2009-10-14 15:52:38.000000000 +0200 ++++ head-2009-10-12/lib/swiotlb-xen.c 2009-10-14 16:20:35.000000000 +0200 +@@ -211,8 +211,8 @@ swiotlb_init_with_default_size(size_t de + void __init + swiotlb_init(void) + { +- long ram_end; +- size_t defsz = 64 * (1 << 20); /* 64MB default size */ ++ unsigned long ram_end; ++ size_t defsz = 64 << 20; /* 64MB default size */ + + if (swiotlb_force == 1) { + swiotlb = 1; +@@ -221,8 +221,12 @@ swiotlb_init(void) + is_initial_xendomain()) { + /* Domain 0 always has a swiotlb. */ + ram_end = HYPERVISOR_memory_op(XENMEM_maximum_ram_page, NULL); +- if (ram_end <= 0x7ffff) +- defsz = 2 * (1 << 20); /* 2MB on <2GB on systems. */ ++ if (ram_end <= 0x1ffff) ++ defsz = 2 << 20; /* 2MB on <512MB systems. */ ++ else if (ram_end <= 0x3ffff) ++ defsz = 4 << 20; /* 4MB on <1GB systems. */ ++ else if (ram_end <= 0x7ffff) ++ defsz = 8 << 20; /* 8MB on <2GB systems. */ + swiotlb = 1; + } + diff --git a/xen-sysdev-suspend b/xen-sysdev-suspend new file mode 100644 index 0000000..b565291 --- /dev/null +++ b/xen-sysdev-suspend @@ -0,0 +1,506 @@ +From: jbeulich@novell.com +Subject: use base kernel suspend/resume infrastructure +Patch-mainline: obsolete + +... rather than calling just a few functions explicitly. + +--- sle11sp1-2010-03-01.orig/arch/x86/kernel/time-xen.c 2010-03-01 14:45:54.000000000 +0100 ++++ sle11sp1-2010-03-01/arch/x86/kernel/time-xen.c 2010-03-01 14:46:04.000000000 +0100 +@@ -69,6 +69,10 @@ static DEFINE_PER_CPU(struct vcpu_runsta + /* Must be signed, as it's compared with s64 quantities which can be -ve. */ + #define NS_PER_TICK (1000000000LL/HZ) + ++static struct vcpu_set_periodic_timer xen_set_periodic_tick = { ++ .period_ns = NS_PER_TICK ++}; ++ + static void __clock_was_set(struct work_struct *unused) + { + clock_was_set(); +@@ -559,6 +563,17 @@ void mark_tsc_unstable(char *reason) + } + EXPORT_SYMBOL_GPL(mark_tsc_unstable); + ++static void init_missing_ticks_accounting(unsigned int cpu) ++{ ++ struct vcpu_runstate_info *runstate = setup_runstate_area(cpu); ++ ++ per_cpu(processed_blocked_time, cpu) = ++ runstate->time[RUNSTATE_blocked]; ++ per_cpu(processed_stolen_time, cpu) = ++ runstate->time[RUNSTATE_runnable] + ++ runstate->time[RUNSTATE_offline]; ++} ++ + static cycle_t cs_last; + + static cycle_t xen_clocksource_read(struct clocksource *cs) +@@ -595,11 +610,32 @@ static cycle_t xen_clocksource_read(stru + #endif + } + ++/* No locking required. Interrupts are disabled on all CPUs. */ + static void xen_clocksource_resume(void) + { +- extern void time_resume(void); ++ unsigned int cpu; ++ ++ init_cpu_khz(); ++ ++ for_each_online_cpu(cpu) { ++ switch (HYPERVISOR_vcpu_op(VCPUOP_set_periodic_timer, cpu, ++ &xen_set_periodic_tick)) { ++ case 0: ++#if CONFIG_XEN_COMPAT <= 0x030004 ++ case -ENOSYS: ++#endif ++ break; ++ default: ++ BUG(); ++ } ++ get_time_values_from_xen(cpu); ++ per_cpu(processed_system_time, cpu) = ++ per_cpu(shadow_time, 0).system_timestamp; ++ init_missing_ticks_accounting(cpu); ++ } ++ ++ processed_system_time = per_cpu(shadow_time, 0).system_timestamp; + +- time_resume(); + cs_last = local_clock(); + } + +@@ -631,17 +667,6 @@ struct vcpu_runstate_info *setup_runstat + return runstate; + } + +-static void init_missing_ticks_accounting(unsigned int cpu) +-{ +- struct vcpu_runstate_info *runstate = setup_runstate_area(cpu); +- +- per_cpu(processed_blocked_time, cpu) = +- runstate->time[RUNSTATE_blocked]; +- per_cpu(processed_stolen_time, cpu) = +- runstate->time[RUNSTATE_runnable] + +- runstate->time[RUNSTATE_offline]; +-} +- + void xen_read_persistent_clock(struct timespec *ts) + { + const shared_info_t *s = HYPERVISOR_shared_info; +@@ -687,10 +712,6 @@ static void __init setup_cpu0_timer_irq( + BUG_ON(per_cpu(timer_irq, 0) < 0); + } + +-static struct vcpu_set_periodic_timer xen_set_periodic_tick = { +- .period_ns = NS_PER_TICK +-}; +- + void __init time_init(void) + { + init_cpu_khz(); +@@ -828,35 +849,6 @@ void xen_halt(void) + } + EXPORT_SYMBOL(xen_halt); + +-/* No locking required. Interrupts are disabled on all CPUs. */ +-void time_resume(void) +-{ +- unsigned int cpu; +- +- init_cpu_khz(); +- +- for_each_online_cpu(cpu) { +- switch (HYPERVISOR_vcpu_op(VCPUOP_set_periodic_timer, cpu, +- &xen_set_periodic_tick)) { +- case 0: +-#if CONFIG_XEN_COMPAT <= 0x030004 +- case -ENOSYS: +-#endif +- break; +- default: +- BUG(); +- } +- get_time_values_from_xen(cpu); +- per_cpu(processed_system_time, cpu) = +- per_cpu(shadow_time, 0).system_timestamp; +- init_missing_ticks_accounting(cpu); +- } +- +- processed_system_time = per_cpu(shadow_time, 0).system_timestamp; +- +- update_wallclock(); +-} +- + #ifdef CONFIG_SMP + static char timer_name[NR_CPUS][15]; + +--- sle11sp1-2010-03-01.orig/drivers/xen/core/evtchn.c 2009-11-06 11:04:38.000000000 +0100 ++++ sle11sp1-2010-03-01/drivers/xen/core/evtchn.c 2010-02-09 17:18:45.000000000 +0100 +@@ -35,6 +35,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -1115,10 +1116,21 @@ static void restore_cpu_ipis(unsigned in + } + } + +-void irq_resume(void) ++static int evtchn_resume(struct sys_device *dev) + { + unsigned int cpu, irq, evtchn; + struct irq_cfg *cfg; ++ struct evtchn_status status; ++ ++ /* Avoid doing anything in the 'suspend cancelled' case. */ ++ status.dom = DOMID_SELF; ++ status.port = evtchn_from_irq(percpu_read(virq_to_irq[VIRQ_TIMER])); ++ if (HYPERVISOR_event_channel_op(EVTCHNOP_status, &status)) ++ BUG(); ++ if (status.status == EVTCHNSTAT_virq ++ && status.vcpu == smp_processor_id() ++ && status.u.virq == VIRQ_TIMER) ++ return 0; + + init_evtchn_cpu_bindings(); + +@@ -1154,7 +1166,32 @@ void irq_resume(void) + restore_cpu_ipis(cpu); + } + ++ return 0; ++} ++ ++static struct sysdev_class evtchn_sysclass = { ++ .name = "evtchn", ++ .resume = evtchn_resume, ++}; ++ ++static struct sys_device device_evtchn = { ++ .id = 0, ++ .cls = &evtchn_sysclass, ++}; ++ ++static int __init evtchn_register(void) ++{ ++ int err; ++ ++ if (is_initial_xendomain()) ++ return 0; ++ ++ err = sysdev_class_register(&evtchn_sysclass); ++ if (!err) ++ err = sysdev_register(&device_evtchn); ++ return err; + } ++core_initcall(evtchn_register); + #endif + + int __init arch_early_irq_init(void) +--- sle11sp1-2010-03-01.orig/drivers/xen/core/gnttab.c 2009-12-15 09:24:56.000000000 +0100 ++++ sle11sp1-2010-03-01/drivers/xen/core/gnttab.c 2009-12-15 09:28:00.000000000 +0100 +@@ -35,6 +35,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -707,23 +708,37 @@ EXPORT_SYMBOL(gnttab_post_map_adjust); + + #endif /* __HAVE_ARCH_PTE_SPECIAL */ + +-int gnttab_resume(void) ++static int gnttab_resume(struct sys_device *dev) + { + if (max_nr_grant_frames() < nr_grant_frames) + return -ENOSYS; + return gnttab_map(0, nr_grant_frames - 1); + } ++#define gnttab_resume() gnttab_resume(NULL) + + #ifdef CONFIG_PM_SLEEP +-int gnttab_suspend(void) +-{ + #ifdef CONFIG_X86 ++static int gnttab_suspend(struct sys_device *dev, pm_message_t state) ++{ + apply_to_page_range(&init_mm, (unsigned long)shared, + PAGE_SIZE * nr_grant_frames, + unmap_pte_fn, NULL); +-#endif + return 0; + } ++#else ++#define gnttab_suspend NULL ++#endif ++ ++static struct sysdev_class gnttab_sysclass = { ++ .name = "gnttab", ++ .resume = gnttab_resume, ++ .suspend = gnttab_suspend, ++}; ++ ++static struct sys_device device_gnttab = { ++ .id = 0, ++ .cls = &gnttab_sysclass, ++}; + #endif + + #else /* !CONFIG_XEN */ +@@ -803,6 +818,17 @@ int __devinit gnttab_init(void) + if (!is_running_on_xen()) + return -ENODEV; + ++#if defined(CONFIG_XEN) && defined(CONFIG_PM_SLEEP) ++ if (!is_initial_xendomain()) { ++ int err = sysdev_class_register(&gnttab_sysclass); ++ ++ if (!err) ++ err = sysdev_register(&device_gnttab); ++ if (err) ++ return err; ++ } ++#endif ++ + nr_grant_frames = 1; + boot_max_nr_grant_frames = __max_nr_grant_frames(); + +--- sle11sp1-2010-03-01.orig/drivers/xen/core/machine_reboot.c 2009-12-18 13:34:27.000000000 +0100 ++++ sle11sp1-2010-03-01/drivers/xen/core/machine_reboot.c 2009-12-18 14:19:13.000000000 +0100 +@@ -17,6 +17,7 @@ + #include + #include + #include ++#include "../../base/base.h" + + #if defined(__i386__) || defined(__x86_64__) + #include +@@ -145,47 +146,28 @@ struct suspend { + static int take_machine_down(void *_suspend) + { + struct suspend *suspend = _suspend; +- int suspend_cancelled, err; +- extern void time_resume(void); ++ int suspend_cancelled; + +- if (suspend->fast_suspend) { +- BUG_ON(!irqs_disabled()); +- } else { +- BUG_ON(irqs_disabled()); +- +- for (;;) { +- err = smp_suspend(); +- if (err) +- return err; +- +- xenbus_suspend(); +- preempt_disable(); +- +- if (num_online_cpus() == 1) +- break; +- +- preempt_enable(); +- xenbus_suspend_cancel(); +- } +- +- local_irq_disable(); +- } ++ BUG_ON(!irqs_disabled()); + + mm_pin_all(); +- gnttab_suspend(); +- pre_suspend(); +- +- /* +- * This hypercall returns 1 if suspend was cancelled or the domain was +- * merely checkpointed, and 0 if it is resuming in a new domain. +- */ +- suspend_cancelled = HYPERVISOR_suspend(virt_to_mfn(xen_start_info)); ++ suspend_cancelled = sysdev_suspend(PMSG_SUSPEND); ++ if (!suspend_cancelled) { ++ pre_suspend(); + ++ /* ++ * This hypercall returns 1 if suspend was cancelled or the domain was ++ * merely checkpointed, and 0 if it is resuming in a new domain. ++ */ ++ suspend_cancelled = HYPERVISOR_suspend(virt_to_mfn(xen_start_info)); ++ } else ++ BUG_ON(suspend_cancelled > 0); + suspend->resume_notifier(suspend_cancelled); +- post_suspend(suspend_cancelled); +- gnttab_resume(); ++ if (suspend_cancelled >= 0) { ++ post_suspend(suspend_cancelled); ++ sysdev_resume(); ++ } + if (!suspend_cancelled) { +- irq_resume(); + #ifdef __x86_64__ + /* + * Older versions of Xen do not save/restore the user %cr3. +@@ -197,10 +179,6 @@ static int take_machine_down(void *_susp + current->active_mm->pgd))); + #endif + } +- time_resume(); +- +- if (!suspend->fast_suspend) +- local_irq_enable(); + + return suspend_cancelled; + } +@@ -208,8 +186,14 @@ static int take_machine_down(void *_susp + int __xen_suspend(int fast_suspend, void (*resume_notifier)(int)) + { + int err, suspend_cancelled; ++ const char *what; + struct suspend suspend; + ++#define _check(fn, args...) ({ \ ++ what = #fn; \ ++ err = (fn)(args); \ ++}) ++ + BUG_ON(smp_processor_id() != 0); + BUG_ON(in_interrupt()); + +@@ -225,41 +209,91 @@ int __xen_suspend(int fast_suspend, void + if (num_possible_cpus() == 1) + fast_suspend = 0; + +- if (fast_suspend) { +- err = stop_machine_create(); +- if (err) +- return err; ++ if (fast_suspend && _check(stop_machine_create)) { ++ printk(KERN_ERR "%s() failed: %d\n", what, err); ++ return err; + } + + suspend.fast_suspend = fast_suspend; + suspend.resume_notifier = resume_notifier; + ++ if (_check(dpm_suspend_start, PMSG_SUSPEND)) { ++ if (fast_suspend) ++ stop_machine_destroy(); ++ printk(KERN_ERR "%s() failed: %d\n", what, err); ++ return err; ++ } ++ + if (fast_suspend) { + xenbus_suspend(); ++ ++ if (_check(dpm_suspend_noirq, PMSG_SUSPEND)) { ++ xenbus_suspend_cancel(); ++ dpm_resume_end(PMSG_RESUME); ++ stop_machine_destroy(); ++ printk(KERN_ERR "%s() failed: %d\n", what, err); ++ return err; ++ } ++ + err = stop_machine(take_machine_down, &suspend, + &cpumask_of_cpu(0)); + if (err < 0) + xenbus_suspend_cancel(); + } else { ++ BUG_ON(irqs_disabled()); ++ ++ for (;;) { ++ xenbus_suspend(); ++ ++ if (!_check(dpm_suspend_noirq, PMSG_SUSPEND) ++ && _check(smp_suspend)) ++ dpm_resume_noirq(PMSG_RESUME); ++ if (err) { ++ xenbus_suspend_cancel(); ++ dpm_resume_end(PMSG_RESUME); ++ printk(KERN_ERR "%s() failed: %d\n", ++ what, err); ++ return err; ++ } ++ ++ preempt_disable(); ++ ++ if (num_online_cpus() == 1) ++ break; ++ ++ preempt_enable(); ++ ++ dpm_resume_noirq(PMSG_RESUME); ++ ++ xenbus_suspend_cancel(); ++ } ++ ++ local_irq_disable(); + err = take_machine_down(&suspend); ++ local_irq_enable(); + } + +- if (err < 0) +- return err; ++ dpm_resume_noirq(PMSG_RESUME); + +- suspend_cancelled = err; +- if (!suspend_cancelled) { +- xencons_resume(); +- xenbus_resume(); +- } else { +- xenbus_suspend_cancel(); ++ if (err >= 0) { ++ suspend_cancelled = err; ++ if (!suspend_cancelled) { ++ xencons_resume(); ++ xenbus_resume(); ++ } else { ++ xenbus_suspend_cancel(); ++ err = 0; ++ } ++ ++ if (!fast_suspend) ++ smp_resume(); + } + +- if (!fast_suspend) +- smp_resume(); +- else ++ dpm_resume_end(PMSG_RESUME); ++ ++ if (fast_suspend) + stop_machine_destroy(); + +- return 0; ++ return err; + } + #endif +--- sle11sp1-2010-03-01.orig/include/xen/evtchn.h 2009-12-18 10:10:04.000000000 +0100 ++++ sle11sp1-2010-03-01/include/xen/evtchn.h 2009-12-18 10:13:12.000000000 +0100 +@@ -107,7 +107,9 @@ int bind_ipi_to_irqhandler( + */ + void unbind_from_irqhandler(unsigned int irq, void *dev_id); + ++#ifndef CONFIG_XEN + void irq_resume(void); ++#endif + + /* Entry point for notifications into Linux subsystems. */ + asmlinkage void evtchn_do_upcall(struct pt_regs *regs); +--- sle11sp1-2010-03-01.orig/include/xen/gnttab.h 2008-11-04 11:13:10.000000000 +0100 ++++ sle11sp1-2010-03-01/include/xen/gnttab.h 2009-11-06 11:10:15.000000000 +0100 +@@ -110,8 +110,9 @@ static inline void __gnttab_dma_unmap_pa + + void gnttab_reset_grant_page(struct page *page); + +-int gnttab_suspend(void); ++#ifndef CONFIG_XEN + int gnttab_resume(void); ++#endif + + void *arch_gnttab_alloc_shared(unsigned long *frames); + diff --git a/xen-unpriv-build b/xen-unpriv-build new file mode 100644 index 0000000..bd807b0 --- /dev/null +++ b/xen-unpriv-build @@ -0,0 +1,292 @@ +From: jbeulich@novell.com +Subject: no need to build certain bits when building non-privileged kernel +Patch-mainline: n/a + +--- sle11sp1-2010-03-29.orig/arch/x86/Kconfig 2010-02-09 17:06:32.000000000 +0100 ++++ sle11sp1-2010-03-29/arch/x86/Kconfig 2010-02-09 17:19:17.000000000 +0100 +@@ -698,6 +698,7 @@ config HPET_EMULATE_RTC + config DMI + default y + bool "Enable DMI scanning" if EMBEDDED ++ depends on !XEN_UNPRIVILEGED_GUEST + ---help--- + Enabled scanning of DMI to identify machine quirks. Say Y + here unless you have verified that your setup is not +@@ -778,6 +779,7 @@ config AMD_IOMMU_STATS + # need this always selected by IOMMU for the VIA workaround + config SWIOTLB + def_bool y if X86_64 || XEN ++ prompt "Software I/O TLB" if XEN_UNPRIVILEGED_GUEST && !XEN_PCIDEV_FRONTEND + ---help--- + Support for software bounce buffers used on x86-64 systems + which don't have a hardware IOMMU (e.g. the current generation +@@ -1974,13 +1976,15 @@ config PCI_GOBIOS + + config PCI_GOMMCONFIG + bool "MMConfig" ++ depends on !XEN_UNPRIVILEGED_GUEST + + config PCI_GODIRECT + bool "Direct" ++ depends on !XEN_UNPRIVILEGED_GUEST + + config PCI_GOOLPC + bool "OLPC" +- depends on OLPC ++ depends on OLPC && !XEN_UNPRIVILEGED_GUEST + + config PCI_GOXEN_FE + bool "Xen PCI Frontend" +@@ -1991,6 +1995,7 @@ config PCI_GOXEN_FE + + config PCI_GOANY + bool "Any" ++ depends on !XEN_UNPRIVILEGED_GUEST + + endchoice + +@@ -2021,7 +2026,7 @@ config PCI_MMCONFIG + + config XEN_PCIDEV_FRONTEND + def_bool y +- prompt "Xen PCI Frontend" if X86_64 ++ prompt "Xen PCI Frontend" if X86_64 && !XEN_UNPRIVILEGED_GUEST + depends on PCI && XEN && (PCI_GOXEN_FE || PCI_GOANY || X86_64) + select HOTPLUG + help +@@ -2226,7 +2231,9 @@ source "net/Kconfig" + + source "drivers/Kconfig" + ++if !XEN_UNPRIVILEGED_GUEST + source "drivers/firmware/Kconfig" ++endif + + source "fs/Kconfig" + +--- sle11sp1-2010-03-29.orig/arch/x86/include/mach-xen/asm/swiotlb.h 2009-11-06 10:51:32.000000000 +0100 ++++ sle11sp1-2010-03-29/arch/x86/include/mach-xen/asm/swiotlb.h 2010-01-27 15:05:03.000000000 +0100 +@@ -1,4 +1,8 @@ + #include_next + ++#ifndef CONFIG_SWIOTLB ++#define swiotlb_init() ++#endif ++ + dma_addr_t swiotlb_map_single_phys(struct device *, phys_addr_t, size_t size, + int dir); +--- sle11sp1-2010-03-29.orig/drivers/firmware/Kconfig 2009-11-06 10:51:32.000000000 +0100 ++++ sle11sp1-2010-03-29/drivers/firmware/Kconfig 2009-11-06 11:10:32.000000000 +0100 +@@ -114,7 +114,7 @@ config DMIID + + config ISCSI_IBFT_FIND + bool "iSCSI Boot Firmware Table Attributes" +- depends on X86 && !XEN_UNPRIVILEGED_GUEST ++ depends on X86 + default n + help + This option enables the kernel to find the region of memory +--- sle11sp1-2010-03-29.orig/drivers/xen/Kconfig 2010-03-29 09:13:14.000000000 +0200 ++++ sle11sp1-2010-03-29/drivers/xen/Kconfig 2010-03-29 09:13:58.000000000 +0200 +@@ -274,6 +274,7 @@ config XEN_USB_FRONTEND_HCD_PM + + config XEN_GRANT_DEV + tristate "User-space granted page access driver" ++ depends on XEN_BACKEND != n + default XEN_PRIVILEGED_GUEST + help + Device for accessing (in user-space) pages that have been granted +--- sle11sp1-2010-03-29.orig/drivers/xen/balloon/balloon.c 2010-02-02 15:08:54.000000000 +0100 ++++ sle11sp1-2010-03-29/drivers/xen/balloon/balloon.c 2010-03-31 10:00:17.000000000 +0200 +@@ -663,6 +663,9 @@ void balloon_update_driver_allowance(lon + bs.driver_pages += delta; + balloon_unlock(flags); + } ++EXPORT_SYMBOL_GPL(balloon_update_driver_allowance); ++ ++#if defined(CONFIG_XEN_BACKEND) || defined(CONFIG_XEN_BACKEND_MODULE) + + #ifdef CONFIG_XEN + static int dealloc_pte_fn( +@@ -771,6 +774,7 @@ struct page **alloc_empty_pages_and_page + pagevec = NULL; + goto out; + } ++EXPORT_SYMBOL_GPL(alloc_empty_pages_and_pagevec); + + void free_empty_pages_and_pagevec(struct page **pagevec, int nr_pages) + { +@@ -791,6 +795,9 @@ void free_empty_pages_and_pagevec(struct + + schedule_work(&balloon_worker); + } ++EXPORT_SYMBOL_GPL(free_empty_pages_and_pagevec); ++ ++#endif /* CONFIG_XEN_BACKEND */ + + void balloon_release_driver_page(struct page *page) + { +@@ -804,10 +811,6 @@ void balloon_release_driver_page(struct + + schedule_work(&balloon_worker); + } +- +-EXPORT_SYMBOL_GPL(balloon_update_driver_allowance); +-EXPORT_SYMBOL_GPL(alloc_empty_pages_and_pagevec); +-EXPORT_SYMBOL_GPL(free_empty_pages_and_pagevec); + EXPORT_SYMBOL_GPL(balloon_release_driver_page); + + MODULE_LICENSE("Dual BSD/GPL"); +--- sle11sp1-2010-03-29.orig/drivers/xen/core/Makefile 2010-01-04 16:17:00.000000000 +0100 ++++ sle11sp1-2010-03-29/drivers/xen/core/Makefile 2009-11-06 11:10:32.000000000 +0100 +@@ -2,9 +2,10 @@ + # Makefile for the linux kernel. + # + +-obj-y := evtchn.o gnttab.o reboot.o machine_reboot.o firmware.o ++obj-y := evtchn.o gnttab.o reboot.o machine_reboot.o + +-obj-$(CONFIG_PCI) += pci.o ++priv-$(CONFIG_PCI) += pci.o ++obj-$(CONFIG_XEN_PRIVILEGED_GUEST) += firmware.o $(priv-y) + obj-$(CONFIG_PROC_FS) += xen_proc.o + obj-$(CONFIG_SYS_HYPERVISOR) += hypervisor_sysfs.o + obj-$(CONFIG_HOTPLUG_CPU) += cpu_hotplug.o +--- sle11sp1-2010-03-29.orig/drivers/xen/core/gnttab.c 2010-02-02 15:10:01.000000000 +0100 ++++ sle11sp1-2010-03-29/drivers/xen/core/gnttab.c 2009-12-15 09:29:45.000000000 +0100 +@@ -437,8 +437,6 @@ static inline unsigned int max_nr_grant_ + + #ifdef CONFIG_XEN + +-static DEFINE_SEQLOCK(gnttab_dma_lock); +- + #ifdef CONFIG_X86 + static int map_pte_fn(pte_t *pte, struct page *pmd_page, + unsigned long addr, void *data) +@@ -508,6 +506,10 @@ static int gnttab_map(unsigned int start + return 0; + } + ++#if defined(CONFIG_XEN_BACKEND) || defined(CONFIG_XEN_BACKEND_MODULE) ++ ++static DEFINE_SEQLOCK(gnttab_dma_lock); ++ + static void gnttab_page_free(struct page *page, unsigned int order) + { + BUG_ON(order); +@@ -639,6 +641,8 @@ void __gnttab_dma_map_page(struct page * + } while (unlikely(read_seqretry(&gnttab_dma_lock, seq))); + } + ++#endif /* CONFIG_XEN_BACKEND */ ++ + #ifdef __HAVE_ARCH_PTE_SPECIAL + + static unsigned int GNTMAP_pte_special; +--- sle11sp1-2010-03-29.orig/drivers/xen/privcmd/Makefile 2007-07-10 09:42:30.000000000 +0200 ++++ sle11sp1-2010-03-29/drivers/xen/privcmd/Makefile 2009-12-18 08:20:46.000000000 +0100 +@@ -1,3 +1,3 @@ +- +-obj-y += privcmd.o +-obj-$(CONFIG_COMPAT) += compat_privcmd.o ++priv-$(CONFIG_COMPAT) := compat_privcmd.o ++obj-y := privcmd.o ++obj-$(CONFIG_XEN_PRIVILEGED_GUEST) += $(priv-y) +--- sle11sp1-2010-03-29.orig/drivers/xen/privcmd/privcmd.c 2010-01-27 14:39:09.000000000 +0100 ++++ sle11sp1-2010-03-29/drivers/xen/privcmd/privcmd.c 2010-01-27 15:05:18.000000000 +0100 +@@ -33,6 +33,9 @@ + static struct proc_dir_entry *privcmd_intf; + static struct proc_dir_entry *capabilities_intf; + ++#ifndef CONFIG_XEN_PRIVILEGED_GUEST ++#define HAVE_ARCH_PRIVCMD_MMAP ++#endif + #ifndef HAVE_ARCH_PRIVCMD_MMAP + static int enforce_singleshot_mapping_fn(pte_t *pte, struct page *pmd_page, + unsigned long addr, void *data) +@@ -57,12 +60,14 @@ static long privcmd_ioctl(struct file *f + { + long ret; + void __user *udata = (void __user *) data; ++#ifdef CONFIG_XEN_PRIVILEGED_GUEST + unsigned long i, addr, nr, nr_pages; + int paged_out; + struct mm_struct *mm = current->mm; + struct vm_area_struct *vma; + LIST_HEAD(pagelist); + struct list_head *l, *l2; ++#endif + + switch (cmd) { + case IOCTL_PRIVCMD_HYPERCALL: { +@@ -87,6 +92,8 @@ static long privcmd_ioctl(struct file *f + } + break; + ++#ifdef CONFIG_XEN_PRIVILEGED_GUEST ++ + case IOCTL_PRIVCMD_MMAP: { + #define MMAP_NR_PER_PAGE \ + (unsigned long)((PAGE_SIZE - sizeof(*l)) / sizeof(*msg)) +@@ -392,6 +399,8 @@ static long privcmd_ioctl(struct file *f + } + break; + ++#endif /* CONFIG_XEN_PRIVILEGED_GUEST */ ++ + default: + ret = -EINVAL; + break; +@@ -427,7 +436,9 @@ static int privcmd_mmap(struct file * fi + + static const struct file_operations privcmd_file_ops = { + .unlocked_ioctl = privcmd_ioctl, ++#ifdef CONFIG_XEN_PRIVILEGED_GUEST + .mmap = privcmd_mmap, ++#endif + }; + + static int capabilities_read(char *page, char **start, off_t off, +--- sle11sp1-2010-03-29.orig/fs/compat_ioctl.c 2010-03-05 10:13:02.000000000 +0100 ++++ sle11sp1-2010-03-29/fs/compat_ioctl.c 2010-03-05 10:25:22.000000000 +0100 +@@ -2741,10 +2741,12 @@ IGNORE_IOCTL(FBIOSCURSOR32) + IGNORE_IOCTL(FBIOGCURSOR32) + #endif + +-#ifdef CONFIG_XEN ++#ifdef CONFIG_XEN_PRIVILEGED_GUEST + HANDLE_IOCTL(IOCTL_PRIVCMD_MMAP_32, privcmd_ioctl_32) + HANDLE_IOCTL(IOCTL_PRIVCMD_MMAPBATCH_32, privcmd_ioctl_32) + HANDLE_IOCTL(IOCTL_PRIVCMD_MMAPBATCH_V2_32, privcmd_ioctl_32) ++#endif ++#ifdef CONFIG_XEN + COMPATIBLE_IOCTL(IOCTL_PRIVCMD_HYPERCALL) + COMPATIBLE_IOCTL(IOCTL_EVTCHN_BIND_VIRQ) + COMPATIBLE_IOCTL(IOCTL_EVTCHN_BIND_INTERDOMAIN) +--- sle11sp1-2010-03-29.orig/include/xen/firmware.h 2007-07-02 08:16:19.000000000 +0200 ++++ sle11sp1-2010-03-29/include/xen/firmware.h 2009-11-06 11:10:32.000000000 +0100 +@@ -5,6 +5,10 @@ + void copy_edd(void); + #endif + ++#ifdef CONFIG_XEN_PRIVILEGED_GUEST + void copy_edid(void); ++#else ++static inline void copy_edid(void) {} ++#endif + + #endif /* __XEN_FIRMWARE_H__ */ +--- sle11sp1-2010-03-29.orig/include/xen/gnttab.h 2009-11-06 11:10:15.000000000 +0100 ++++ sle11sp1-2010-03-29/include/xen/gnttab.h 2009-12-15 09:54:17.000000000 +0100 +@@ -103,7 +103,11 @@ void gnttab_grant_foreign_transfer_ref(g + unsigned long pfn); + + int gnttab_copy_grant_page(grant_ref_t ref, struct page **pagep); ++#if defined(CONFIG_XEN_BACKEND) || defined(CONFIG_XEN_BACKEND_MODULE) + void __gnttab_dma_map_page(struct page *page); ++#else ++#define __gnttab_dma_map_page __gnttab_dma_unmap_page ++#endif + static inline void __gnttab_dma_unmap_page(struct page *page) + { + } diff --git a/xen-virq-per-cpu-irq b/xen-virq-per-cpu-irq new file mode 100644 index 0000000..43c36a6 --- /dev/null +++ b/xen-virq-per-cpu-irq @@ -0,0 +1,649 @@ +From: jbeulich@novell.com +Subject: fold per-CPU VIRQs onto a single IRQ each +Patch-mainline: obsolete + +--- sle11sp1-2010-03-22.orig/arch/x86/kernel/time-xen.c 2010-03-01 14:46:04.000000000 +0100 ++++ sle11sp1-2010-03-22/arch/x86/kernel/time-xen.c 2010-03-01 14:46:13.000000000 +0100 +@@ -697,19 +697,17 @@ int xen_update_persistent_clock(void) + } + + /* Dynamically-mapped IRQ. */ +-DEFINE_PER_CPU(int, timer_irq); ++static int __read_mostly timer_irq = -1; ++static struct irqaction timer_action = { ++ .handler = timer_interrupt, ++ .flags = IRQF_DISABLED|IRQF_TIMER, ++ .name = "timer" ++}; + + static void __init setup_cpu0_timer_irq(void) + { +- per_cpu(timer_irq, 0) = +- bind_virq_to_irqhandler( +- VIRQ_TIMER, +- 0, +- timer_interrupt, +- IRQF_DISABLED|IRQF_TIMER|IRQF_NOBALANCING, +- "timer0", +- NULL); +- BUG_ON(per_cpu(timer_irq, 0) < 0); ++ timer_irq = bind_virq_to_irqaction(VIRQ_TIMER, 0, &timer_action); ++ BUG_ON(timer_irq < 0); + } + + void __init time_init(void) +@@ -850,8 +848,6 @@ void xen_halt(void) + EXPORT_SYMBOL(xen_halt); + + #ifdef CONFIG_SMP +-static char timer_name[NR_CPUS][15]; +- + int __cpuinit local_setup_timer(unsigned int cpu) + { + int seq, irq; +@@ -877,16 +873,10 @@ int __cpuinit local_setup_timer(unsigned + init_missing_ticks_accounting(cpu); + } while (read_seqretry(&xtime_lock, seq)); + +- sprintf(timer_name[cpu], "timer%u", cpu); +- irq = bind_virq_to_irqhandler(VIRQ_TIMER, +- cpu, +- timer_interrupt, +- IRQF_DISABLED|IRQF_TIMER|IRQF_NOBALANCING, +- timer_name[cpu], +- NULL); ++ irq = bind_virq_to_irqaction(VIRQ_TIMER, cpu, &timer_action); + if (irq < 0) + return irq; +- per_cpu(timer_irq, cpu) = irq; ++ BUG_ON(timer_irq != irq); + + return 0; + } +@@ -894,7 +884,7 @@ int __cpuinit local_setup_timer(unsigned + void __cpuinit local_teardown_timer(unsigned int cpu) + { + BUG_ON(cpu == 0); +- unbind_from_irqhandler(per_cpu(timer_irq, cpu), NULL); ++ unbind_from_per_cpu_irq(timer_irq, cpu, &timer_action); + } + #endif + +--- sle11sp1-2010-03-22.orig/drivers/xen/core/evtchn.c 2010-02-09 17:18:51.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/xen/core/evtchn.c 2010-02-09 17:18:55.000000000 +0100 +@@ -58,6 +58,23 @@ static DEFINE_SPINLOCK(irq_mapping_updat + static int evtchn_to_irq[NR_EVENT_CHANNELS] = { + [0 ... NR_EVENT_CHANNELS-1] = -1 }; + ++#if defined(CONFIG_SMP) && defined(CONFIG_X86) ++static struct per_cpu_irqaction { ++ struct irqaction action; /* must be first */ ++ struct per_cpu_irqaction *next; ++ cpumask_t cpus; ++} *virq_actions[NR_VIRQS]; ++/* IRQ <-> VIRQ mapping. */ ++static DECLARE_BITMAP(virq_per_cpu, NR_VIRQS) __read_mostly; ++static DEFINE_PER_CPU(int[NR_VIRQS], virq_to_evtchn); ++#define BUG_IF_VIRQ_PER_CPU(irq) \ ++ BUG_ON(type_from_irq(irq) == IRQT_VIRQ \ ++ && test_bit(index_from_irq(irq), virq_per_cpu)) ++#else ++#define BUG_IF_VIRQ_PER_CPU(irq) ((void)(irq)) ++#define PER_CPU_VIRQ_IRQ ++#endif ++ + /* IRQ <-> IPI mapping. */ + #ifndef NR_IPIS + #define NR_IPIS 1 +@@ -132,15 +149,6 @@ static inline u32 mk_irq_info(u32 type, + * Accessors for packed IRQ information. + */ + +-#ifdef PER_CPU_IPI_IRQ +-static inline unsigned int evtchn_from_irq(int irq) +-{ +- const struct irq_cfg *cfg = irq_cfg(irq); +- +- return cfg ? cfg->info & ((1U << _EVTCHN_BITS) - 1) : 0; +-} +-#endif +- + static inline unsigned int index_from_irq(int irq) + { + const struct irq_cfg *cfg = irq_cfg(irq); +@@ -156,24 +164,39 @@ static inline unsigned int type_from_irq + return cfg ? cfg->info >> (32 - _IRQT_BITS) : IRQT_UNBOUND; + } + +-#ifndef PER_CPU_IPI_IRQ + static inline unsigned int evtchn_from_per_cpu_irq(unsigned int irq, + unsigned int cpu) + { +- BUG_ON(type_from_irq(irq) != IRQT_IPI); +- return per_cpu(ipi_to_evtchn, cpu)[index_from_irq(irq)]; ++ switch (type_from_irq(irq)) { ++#ifndef PER_CPU_VIRQ_IRQ ++ case IRQT_VIRQ: ++ return per_cpu(virq_to_evtchn, cpu)[index_from_irq(irq)]; ++#endif ++#ifndef PER_CPU_IPI_IRQ ++ case IRQT_IPI: ++ return per_cpu(ipi_to_evtchn, cpu)[index_from_irq(irq)]; ++#endif ++ } ++ BUG(); ++ return 0; + } + + static inline unsigned int evtchn_from_irq(unsigned int irq) + { +- if (type_from_irq(irq) != IRQT_IPI) { +- const struct irq_cfg *cfg = irq_cfg(irq); ++ const struct irq_cfg *cfg; + +- return cfg ? cfg->info & ((1U << _EVTCHN_BITS) - 1) : 0; ++ switch (type_from_irq(irq)) { ++#ifndef PER_CPU_VIRQ_IRQ ++ case IRQT_VIRQ: ++#endif ++#ifndef PER_CPU_IPI_IRQ ++ case IRQT_IPI: ++#endif ++ return evtchn_from_per_cpu_irq(irq, smp_processor_id()); + } +- return evtchn_from_per_cpu_irq(irq, smp_processor_id()); ++ cfg = irq_cfg(irq); ++ return cfg ? cfg->info & ((1U << _EVTCHN_BITS) - 1) : 0; + } +-#endif + + /* IRQ <-> VIRQ mapping. */ + DEFINE_PER_CPU(int[NR_VIRQS], virq_to_irq) = {[0 ... NR_VIRQS-1] = -1}; +@@ -516,6 +539,14 @@ static int bind_virq_to_irq(unsigned int + evtchn = bind_virq.port; + + evtchn_to_irq[evtchn] = irq; ++#ifndef PER_CPU_VIRQ_IRQ ++ { ++ unsigned int cpu; ++ ++ for_each_possible_cpu(cpu) ++ per_cpu(virq_to_evtchn, cpu)[virq] = evtchn; ++ } ++#endif + irq_cfg(irq)->info = mk_irq_info(IRQT_VIRQ, virq, evtchn); + + per_cpu(virq_to_irq, cpu)[virq] = irq; +@@ -570,7 +601,9 @@ static void unbind_from_irq(unsigned int + unsigned int cpu; + int evtchn = evtchn_from_irq(irq); + ++ BUG_IF_VIRQ_PER_CPU(irq); + BUG_IF_IPI(irq); ++ + spin_lock(&irq_mapping_update_lock); + + if (!--irq_cfg(irq)->bindcount && VALID_EVTCHN(evtchn)) { +@@ -583,6 +616,11 @@ static void unbind_from_irq(unsigned int + case IRQT_VIRQ: + per_cpu(virq_to_irq, cpu_from_evtchn(evtchn)) + [index_from_irq(irq)] = -1; ++#ifndef PER_CPU_VIRQ_IRQ ++ for_each_possible_cpu(cpu) ++ per_cpu(virq_to_evtchn, cpu) ++ [index_from_irq(irq)] = 0; ++#endif + break; + #if defined(CONFIG_SMP) && defined(PER_CPU_IPI_IRQ) + case IRQT_IPI: +@@ -612,11 +650,13 @@ static void unbind_from_irq(unsigned int + spin_unlock(&irq_mapping_update_lock); + } + +-#if defined(CONFIG_SMP) && !defined(PER_CPU_IPI_IRQ) +-void unbind_from_per_cpu_irq(unsigned int irq, unsigned int cpu) ++#if defined(CONFIG_SMP) && (!defined(PER_CPU_IPI_IRQ) || !defined(PER_CPU_VIRQ_IRQ)) ++void unbind_from_per_cpu_irq(unsigned int irq, unsigned int cpu, ++ struct irqaction *action) + { + struct evtchn_close close; + int evtchn = evtchn_from_per_cpu_irq(irq, cpu); ++ struct irqaction *free_action = NULL; + + spin_lock(&irq_mapping_update_lock); + +@@ -627,6 +667,32 @@ void unbind_from_per_cpu_irq(unsigned in + + BUG_ON(irq_cfg(irq)->bindcount <= 1); + irq_cfg(irq)->bindcount--; ++ ++#ifndef PER_CPU_VIRQ_IRQ ++ if (type_from_irq(irq) == IRQT_VIRQ) { ++ unsigned int virq = index_from_irq(irq); ++ struct per_cpu_irqaction *cur, *prev = NULL; ++ ++ cur = virq_actions[virq]; ++ while (cur) { ++ if (cur->action.dev_id == action) { ++ cpu_clear(cpu, cur->cpus); ++ if (cpus_empty(cur->cpus)) { ++ if (prev) ++ prev->next = cur->next; ++ else ++ virq_actions[virq] = cur->next; ++ free_action = action; ++ } ++ } else if (cpu_isset(cpu, cur->cpus)) ++ evtchn = 0; ++ cur = (prev = cur)->next; ++ } ++ if (!VALID_EVTCHN(evtchn)) ++ goto done; ++ } ++#endif ++ + cpumask_clear_cpu(cpu, desc->affinity); + + close.port = evtchn; +@@ -634,9 +700,16 @@ void unbind_from_per_cpu_irq(unsigned in + BUG(); + + switch (type_from_irq(irq)) { ++#ifndef PER_CPU_VIRQ_IRQ ++ case IRQT_VIRQ: ++ per_cpu(virq_to_evtchn, cpu)[index_from_irq(irq)] = 0; ++ break; ++#endif ++#ifndef PER_CPU_IPI_IRQ + case IRQT_IPI: + per_cpu(ipi_to_evtchn, cpu)[index_from_irq(irq)] = 0; + break; ++#endif + default: + BUG(); + break; +@@ -648,9 +721,16 @@ void unbind_from_per_cpu_irq(unsigned in + evtchn_to_irq[evtchn] = -1; + } + ++#ifndef PER_CPU_VIRQ_IRQ ++done: ++#endif + spin_unlock(&irq_mapping_update_lock); ++ ++ if (free_action) ++ free_irq(irq, free_action); + } +-#endif /* CONFIG_SMP && !PER_CPU_IPI_IRQ */ ++EXPORT_SYMBOL_GPL(unbind_from_per_cpu_irq); ++#endif /* CONFIG_SMP && (!PER_CPU_IPI_IRQ || !PER_CPU_VIRQ_IRQ) */ + + int bind_caller_port_to_irqhandler( + unsigned int caller_port, +@@ -732,6 +812,8 @@ int bind_virq_to_irqhandler( + { + int irq, retval; + ++ BUG_IF_VIRQ_PER_CPU(virq); ++ + irq = bind_virq_to_irq(virq, cpu); + if (irq < 0) + return irq; +@@ -747,6 +829,108 @@ int bind_virq_to_irqhandler( + EXPORT_SYMBOL_GPL(bind_virq_to_irqhandler); + + #ifdef CONFIG_SMP ++#ifndef PER_CPU_VIRQ_IRQ ++int bind_virq_to_irqaction( ++ unsigned int virq, ++ unsigned int cpu, ++ struct irqaction *action) ++{ ++ struct evtchn_bind_virq bind_virq; ++ int evtchn, irq, retval = 0; ++ struct per_cpu_irqaction *cur = NULL, *new; ++ ++ BUG_ON(!test_bit(virq, virq_per_cpu)); ++ ++ if (action->dev_id) ++ return -EINVAL; ++ ++ new = kzalloc(sizeof(*new), GFP_ATOMIC); ++ if (new) { ++ new->action = *action; ++ new->action.dev_id = action; ++ } ++ ++ spin_lock(&irq_mapping_update_lock); ++ ++ for (cur = virq_actions[virq]; cur; cur = cur->next) ++ if (cur->action.dev_id == action) ++ break; ++ if (!cur) { ++ if (!new) { ++ spin_unlock(&irq_mapping_update_lock); ++ return -ENOMEM; ++ } ++ new->next = virq_actions[virq]; ++ virq_actions[virq] = cur = new; ++ retval = 1; ++ } ++ cpu_set(cpu, cur->cpus); ++ action = &cur->action; ++ ++ if ((irq = per_cpu(virq_to_irq, cpu)[virq]) == -1) { ++ unsigned int nr; ++ ++ BUG_ON(!retval); ++ ++ if ((irq = find_unbound_irq(cpu, true)) < 0) { ++ if (cur) ++ virq_actions[virq] = cur->next; ++ spin_unlock(&irq_mapping_update_lock); ++ if (cur != new) ++ kfree(new); ++ return irq; ++ } ++ ++ /* Extra reference so count will never drop to zero. */ ++ irq_cfg(irq)->bindcount++; ++ ++ for_each_possible_cpu(nr) ++ per_cpu(virq_to_irq, nr)[virq] = irq; ++ irq_cfg(irq)->info = mk_irq_info(IRQT_VIRQ, virq, 0); ++ } ++ ++ evtchn = per_cpu(virq_to_evtchn, cpu)[virq]; ++ if (!VALID_EVTCHN(evtchn)) { ++ bind_virq.virq = virq; ++ bind_virq.vcpu = cpu; ++ if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq, ++ &bind_virq) != 0) ++ BUG(); ++ evtchn = bind_virq.port; ++ evtchn_to_irq[evtchn] = irq; ++ per_cpu(virq_to_evtchn, cpu)[virq] = evtchn; ++ ++ bind_evtchn_to_cpu(evtchn, cpu); ++ } ++ ++ irq_cfg(irq)->bindcount++; ++ ++ spin_unlock(&irq_mapping_update_lock); ++ ++ if (cur != new) ++ kfree(new); ++ ++ if (retval == 0) { ++ unsigned long flags; ++ ++ local_irq_save(flags); ++ unmask_evtchn(evtchn); ++ local_irq_restore(flags); ++ } else { ++ action->flags |= IRQF_PERCPU; ++ retval = setup_irq(irq, action); ++ if (retval) { ++ unbind_from_per_cpu_irq(irq, cpu, cur->action.dev_id); ++ BUG_ON(retval > 0); ++ irq = retval; ++ } ++ } ++ ++ return irq; ++} ++EXPORT_SYMBOL_GPL(bind_virq_to_irqaction); ++#endif ++ + #ifdef PER_CPU_IPI_IRQ + int bind_ipi_to_irqhandler( + unsigned int ipi, +@@ -826,7 +1010,7 @@ int __cpuinit bind_ipi_to_irqaction( + action->flags |= IRQF_PERCPU | IRQF_NO_SUSPEND; + retval = setup_irq(irq, action); + if (retval) { +- unbind_from_per_cpu_irq(irq, cpu); ++ unbind_from_per_cpu_irq(irq, cpu, NULL); + BUG_ON(retval > 0); + irq = retval; + } +@@ -861,7 +1045,9 @@ static void rebind_irq_to_cpu(unsigned i + { + int evtchn = evtchn_from_irq(irq); + ++ BUG_IF_VIRQ_PER_CPU(irq); + BUG_IF_IPI(irq); ++ + if (VALID_EVTCHN(evtchn)) + rebind_evtchn_to_cpu(evtchn, tcpu); + } +@@ -1141,7 +1327,9 @@ void notify_remote_via_irq(int irq) + { + int evtchn = evtchn_from_irq(irq); + ++ BUG_ON(type_from_irq(irq) == IRQT_VIRQ); + BUG_IF_IPI(irq); ++ + if (VALID_EVTCHN(evtchn)) + notify_remote_via_evtchn(evtchn); + } +@@ -1149,6 +1337,7 @@ EXPORT_SYMBOL_GPL(notify_remote_via_irq) + + int irq_to_evtchn_port(int irq) + { ++ BUG_IF_VIRQ_PER_CPU(irq); + BUG_IF_IPI(irq); + return evtchn_from_irq(irq); + } +@@ -1243,6 +1432,12 @@ static void restore_cpu_virqs(unsigned i + if ((irq = per_cpu(virq_to_irq, cpu)[virq]) == -1) + continue; + ++#ifndef PER_CPU_VIRQ_IRQ ++ if (test_bit(virq, virq_per_cpu) ++ && !VALID_EVTCHN(per_cpu(virq_to_evtchn, cpu)[virq])) ++ continue; ++#endif ++ + BUG_ON(irq_cfg(irq)->info != mk_irq_info(IRQT_VIRQ, virq, 0)); + + /* Get a new binding from Xen. */ +@@ -1255,7 +1450,20 @@ static void restore_cpu_virqs(unsigned i + + /* Record the new mapping. */ + evtchn_to_irq[evtchn] = irq; ++#ifdef PER_CPU_VIRQ_IRQ + irq_cfg(irq)->info = mk_irq_info(IRQT_VIRQ, virq, evtchn); ++#else ++ if (test_bit(virq, virq_per_cpu)) ++ per_cpu(virq_to_evtchn, cpu)[virq] = evtchn; ++ else { ++ unsigned int cpu; ++ ++ irq_cfg(irq)->info = mk_irq_info(IRQT_VIRQ, virq, ++ evtchn); ++ for_each_possible_cpu(cpu) ++ per_cpu(virq_to_evtchn, cpu)[virq] = evtchn; ++ } ++#endif + bind_evtchn_to_cpu(evtchn, cpu); + + /* Ready for use. */ +@@ -1311,7 +1519,11 @@ static int evtchn_resume(struct sys_devi + + /* Avoid doing anything in the 'suspend cancelled' case. */ + status.dom = DOMID_SELF; ++#ifdef PER_CPU_VIRQ_IRQ + status.port = evtchn_from_irq(percpu_read(virq_to_irq[VIRQ_TIMER])); ++#else ++ status.port = percpu_read(virq_to_evtchn[VIRQ_TIMER]); ++#endif + if (HYPERVISOR_event_channel_op(EVTCHNOP_status, &status)) + BUG(); + if (status.status == EVTCHNSTAT_virq +@@ -1540,6 +1752,15 @@ void __init xen_init_IRQ(void) + unsigned int i; + struct physdev_pirq_eoi_gmfn eoi_gmfn; + ++#ifndef PER_CPU_VIRQ_IRQ ++ __set_bit(VIRQ_TIMER, virq_per_cpu); ++ __set_bit(VIRQ_DEBUG, virq_per_cpu); ++ __set_bit(VIRQ_XENOPROF, virq_per_cpu); ++#ifdef CONFIG_IA64 ++ __set_bit(VIRQ_ITC, virq_per_cpu); ++#endif ++#endif ++ + init_evtchn_cpu_bindings(); + + i = get_order(sizeof(unsigned long) * BITS_TO_LONGS(nr_pirqs)); +--- sle11sp1-2010-03-22.orig/drivers/xen/core/smpboot.c 2010-03-22 12:57:46.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/xen/core/smpboot.c 2010-03-22 12:57:50.000000000 +0100 +@@ -176,13 +176,13 @@ static int __cpuinit xen_smp_intr_init(u + fail: + xen_spinlock_cleanup(cpu); + unbind_reboot: +- unbind_from_per_cpu_irq(reboot_irq, cpu); ++ unbind_from_per_cpu_irq(reboot_irq, cpu, NULL); + unbind_call1: +- unbind_from_per_cpu_irq(call1func_irq, cpu); ++ unbind_from_per_cpu_irq(call1func_irq, cpu, NULL); + unbind_call: +- unbind_from_per_cpu_irq(callfunc_irq, cpu); ++ unbind_from_per_cpu_irq(callfunc_irq, cpu, NULL); + unbind_resched: +- unbind_from_per_cpu_irq(resched_irq, cpu); ++ unbind_from_per_cpu_irq(resched_irq, cpu, NULL); + return rc; + } + +@@ -192,10 +192,10 @@ static void __cpuinit xen_smp_intr_exit( + if (cpu != 0) + local_teardown_timer(cpu); + +- unbind_from_per_cpu_irq(resched_irq, cpu); +- unbind_from_per_cpu_irq(callfunc_irq, cpu); +- unbind_from_per_cpu_irq(call1func_irq, cpu); +- unbind_from_per_cpu_irq(reboot_irq, cpu); ++ unbind_from_per_cpu_irq(resched_irq, cpu, NULL); ++ unbind_from_per_cpu_irq(callfunc_irq, cpu, NULL); ++ unbind_from_per_cpu_irq(call1func_irq, cpu, NULL); ++ unbind_from_per_cpu_irq(reboot_irq, cpu, NULL); + xen_spinlock_cleanup(cpu); + } + #endif +--- sle11sp1-2010-03-22.orig/drivers/xen/core/spinlock.c 2010-02-23 14:25:31.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/xen/core/spinlock.c 2010-02-23 12:31:40.000000000 +0100 +@@ -55,7 +55,7 @@ int __cpuinit xen_spinlock_init(unsigned + + void __cpuinit xen_spinlock_cleanup(unsigned int cpu) + { +- unbind_from_per_cpu_irq(spinlock_irq, cpu); ++ unbind_from_per_cpu_irq(spinlock_irq, cpu, NULL); + } + + static unsigned int spin_adjust(struct spinning *spinning, +--- sle11sp1-2010-03-22.orig/drivers/xen/netback/netback.c 2009-11-06 10:52:23.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/xen/netback/netback.c 2010-01-04 13:31:26.000000000 +0100 +@@ -1619,6 +1619,12 @@ static irqreturn_t netif_be_dbg(int irq, + + return IRQ_HANDLED; + } ++ ++static struct irqaction netif_be_dbg_action = { ++ .handler = netif_be_dbg, ++ .flags = IRQF_SHARED, ++ .name = "net-be-dbg" ++}; + #endif + + static int __init netback_init(void) +@@ -1678,12 +1684,9 @@ static int __init netback_init(void) + netif_xenbus_init(); + + #ifdef NETBE_DEBUG_INTERRUPT +- (void)bind_virq_to_irqhandler(VIRQ_DEBUG, +- 0, +- netif_be_dbg, +- IRQF_SHARED, +- "net-be-dbg", +- &netif_be_dbg); ++ (void)bind_virq_to_irqaction(VIRQ_DEBUG, ++ 0, ++ &netif_be_dbg_action); + #endif + + return 0; +--- sle11sp1-2010-03-22.orig/drivers/xen/xenoprof/xenoprofile.c 2010-01-07 09:59:32.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/xen/xenoprof/xenoprofile.c 2010-01-07 11:04:10.000000000 +0100 +@@ -210,6 +210,11 @@ static irqreturn_t xenoprof_ovf_interrup + return IRQ_HANDLED; + } + ++static struct irqaction ovf_action = { ++ .handler = xenoprof_ovf_interrupt, ++ .flags = IRQF_DISABLED, ++ .name = "xenoprof" ++}; + + static void unbind_virq(void) + { +@@ -217,7 +222,7 @@ static void unbind_virq(void) + + for_each_online_cpu(i) { + if (ovf_irq[i] >= 0) { +- unbind_from_irqhandler(ovf_irq[i], NULL); ++ unbind_from_per_cpu_irq(ovf_irq[i], i, &ovf_action); + ovf_irq[i] = -1; + } + } +@@ -230,12 +235,7 @@ static int bind_virq(void) + int result; + + for_each_online_cpu(i) { +- result = bind_virq_to_irqhandler(VIRQ_XENOPROF, +- i, +- xenoprof_ovf_interrupt, +- IRQF_DISABLED|IRQF_NOBALANCING, +- "xenoprof", +- NULL); ++ result = bind_virq_to_irqaction(VIRQ_XENOPROF, i, &ovf_action); + + if (result < 0) { + unbind_virq(); +--- sle11sp1-2010-03-22.orig/include/xen/evtchn.h 2009-12-18 10:13:26.000000000 +0100 ++++ sle11sp1-2010-03-22/include/xen/evtchn.h 2009-12-18 10:13:32.000000000 +0100 +@@ -92,6 +92,17 @@ int bind_virq_to_irqhandler( + unsigned long irqflags, + const char *devname, + void *dev_id); ++#if defined(CONFIG_SMP) && defined(CONFIG_XEN) && defined(CONFIG_X86) ++int bind_virq_to_irqaction( ++ unsigned int virq, ++ unsigned int cpu, ++ struct irqaction *action); ++#else ++#define bind_virq_to_irqaction(virq, cpu, action) \ ++ bind_virq_to_irqhandler(virq, cpu, (action)->handler, \ ++ (action)->flags | IRQF_NOBALANCING, \ ++ (action)->name, action) ++#endif + #if defined(CONFIG_SMP) && !defined(MODULE) + #ifndef CONFIG_X86 + int bind_ipi_to_irqhandler( +@@ -116,9 +127,13 @@ int bind_ipi_to_irqaction( + */ + void unbind_from_irqhandler(unsigned int irq, void *dev_id); + +-#if defined(CONFIG_SMP) && !defined(MODULE) && defined(CONFIG_X86) ++#if defined(CONFIG_SMP) && defined(CONFIG_XEN) && defined(CONFIG_X86) + /* Specialized unbind function for per-CPU IRQs. */ +-void unbind_from_per_cpu_irq(unsigned int irq, unsigned int cpu); ++void unbind_from_per_cpu_irq(unsigned int irq, unsigned int cpu, ++ struct irqaction *); ++#else ++#define unbind_from_per_cpu_irq(irq, cpu, action) \ ++ unbind_from_irqhandler(irq, action) + #endif + + #ifndef CONFIG_XEN diff --git a/xen-x86-bigmem b/xen-x86-bigmem new file mode 100644 index 0000000..71f9178 --- /dev/null +++ b/xen-x86-bigmem @@ -0,0 +1,143 @@ +From: jbeulich@novell.com +Subject: fix issues with the assignment of huge amounts of memory +Patch-mainline: obsolete +References: bnc#482614, bnc#537435 + +--- sle11sp1-2010-02-09.orig/arch/x86/kernel/e820-xen.c 2009-12-04 11:31:40.000000000 +0100 ++++ sle11sp1-2010-02-09/arch/x86/kernel/e820-xen.c 2009-12-04 12:11:12.000000000 +0100 +@@ -1350,6 +1350,26 @@ static int __init parse_memopt(char *p) + + userdef = 1; + mem_size = memparse(p, &p); ++#ifdef CONFIG_XEN ++ /* ++ * A little less than 2% of available memory are needed for page ++ * tables, p2m map, and mem_map. Hence the maximum amount of memory ++ * we can potentially balloon up to can in no case exceed about 50 ++ * times of what we've been given initially. Since even with that we ++ * won't be able to boot (due to various calculations done based on ++ * the total number of pages) we further restrict this to factor 32. ++ */ ++ if ((mem_size >> (PAGE_SHIFT + 5)) > xen_start_info->nr_pages) { ++ u64 size = (u64)xen_start_info->nr_pages << 5; ++ ++ printk(KERN_WARNING "mem=%Luk is invalid for an initial" ++ " allocation of %luk, using %Luk\n", ++ (unsigned long long)mem_size >> 10, ++ xen_start_info->nr_pages << (PAGE_SHIFT - 10), ++ (unsigned long long)size << (PAGE_SHIFT - 10)); ++ mem_size = size << PAGE_SHIFT; ++ } ++#endif + e820_remove_range(mem_size, ULLONG_MAX - mem_size, E820_RAM, 1); + + i = e820.nr_map - 1; +@@ -1546,6 +1566,7 @@ void __init e820_reserve_resources_late( + char *__init default_machine_specific_memory_setup(void) + { + int rc, nr_map; ++ unsigned long long maxmem; + struct xen_memory_map memmap; + static struct e820entry __initdata map[E820MAX]; + +@@ -1571,6 +1592,22 @@ char *__init default_machine_specific_me + BUG(); + + #ifdef CONFIG_XEN ++ /* See the comment in parse_memopt(). */ ++ for (maxmem = rc = 0; rc < e820.nr_map; ++rc) ++ if (e820.map[rc].type == E820_RAM) ++ maxmem += e820.map[rc].size; ++ if ((maxmem >> (PAGE_SHIFT + 5)) > xen_start_info->nr_pages) { ++ unsigned long long size = (u64)xen_start_info->nr_pages << 5; ++ ++ printk(KERN_WARNING "maxmem of %LuM is invalid for an initial" ++ " allocation of %luM, using %LuM\n", ++ maxmem >> 20, ++ xen_start_info->nr_pages >> (20 - PAGE_SHIFT), ++ size >> (20 - PAGE_SHIFT)); ++ size <<= PAGE_SHIFT; ++ e820_remove_range(size, ULLONG_MAX - size, E820_RAM, 1); ++ } ++ + if (is_initial_xendomain()) { + memmap.nr_entries = E820MAX; + set_xen_guest_handle(memmap.buffer, machine_e820.map); +--- sle11sp1-2010-02-09.orig/arch/x86/kernel/setup-xen.c 2010-02-09 17:19:30.000000000 +0100 ++++ sle11sp1-2010-02-09/arch/x86/kernel/setup-xen.c 2010-02-09 17:19:48.000000000 +0100 +@@ -129,12 +129,7 @@ static struct notifier_block xen_panic_b + unsigned long *phys_to_machine_mapping; + EXPORT_SYMBOL(phys_to_machine_mapping); + +-unsigned long *pfn_to_mfn_frame_list_list, +-#ifdef CONFIG_X86_64 +- *pfn_to_mfn_frame_list[512]; +-#else +- *pfn_to_mfn_frame_list[128]; +-#endif ++unsigned long *pfn_to_mfn_frame_list_list, **pfn_to_mfn_frame_list; + + /* Raw start-of-day parameters from the hypervisor. */ + start_info_t *xen_start_info; +@@ -1153,17 +1148,17 @@ void __init setup_arch(char **cmdline_p) + p2m_pages = xen_start_info->nr_pages; + + if (!xen_feature(XENFEAT_auto_translated_physmap)) { +- unsigned long i, j; ++ unsigned long i, j, size; + unsigned int k, fpp; + + /* Make sure we have a large enough P->M table. */ + phys_to_machine_mapping = alloc_bootmem_pages( + max_pfn * sizeof(unsigned long)); +- memset(phys_to_machine_mapping, ~0, +- max_pfn * sizeof(unsigned long)); + memcpy(phys_to_machine_mapping, + (unsigned long *)xen_start_info->mfn_list, + p2m_pages * sizeof(unsigned long)); ++ memset(phys_to_machine_mapping + p2m_pages, ~0, ++ (max_pfn - p2m_pages) * sizeof(unsigned long)); + free_bootmem( + __pa(xen_start_info->mfn_list), + PFN_PHYS(PFN_UP(xen_start_info->nr_pages * +@@ -1173,15 +1168,26 @@ void __init setup_arch(char **cmdline_p) + * Initialise the list of the frames that specify the list of + * frames that make up the p2m table. Used by save/restore. + */ +- pfn_to_mfn_frame_list_list = alloc_bootmem_pages(PAGE_SIZE); +- + fpp = PAGE_SIZE/sizeof(unsigned long); ++ size = (max_pfn + fpp - 1) / fpp; ++ size = (size + fpp - 1) / fpp; ++ ++size; /* include a zero terminator for crash tools */ ++ size *= sizeof(unsigned long); ++ pfn_to_mfn_frame_list_list = alloc_bootmem_pages(size); ++ if (size > PAGE_SIZE ++ && xen_create_contiguous_region((unsigned long) ++ pfn_to_mfn_frame_list_list, ++ get_order(size), 0)) ++ BUG(); ++ size -= sizeof(unsigned long); ++ pfn_to_mfn_frame_list = alloc_bootmem(size); ++ + for (i = j = 0, k = -1; i < max_pfn; i += fpp, j++) { + if (j == fpp) + j = 0; + if (j == 0) { + k++; +- BUG_ON(k>=ARRAY_SIZE(pfn_to_mfn_frame_list)); ++ BUG_ON(k * sizeof(unsigned long) >= size); + pfn_to_mfn_frame_list[k] = + alloc_bootmem_pages(PAGE_SIZE); + pfn_to_mfn_frame_list_list[k] = +--- sle11sp1-2010-02-09.orig/drivers/xen/core/machine_reboot.c 2009-12-18 14:19:13.000000000 +0100 ++++ sle11sp1-2010-02-09/drivers/xen/core/machine_reboot.c 2009-12-18 14:15:04.000000000 +0100 +@@ -79,7 +79,7 @@ static void post_suspend(int suspend_can + unsigned long shinfo_mfn; + extern unsigned long max_pfn; + extern unsigned long *pfn_to_mfn_frame_list_list; +- extern unsigned long *pfn_to_mfn_frame_list[]; ++ extern unsigned long **pfn_to_mfn_frame_list; + + if (suspend_cancelled) { + xen_start_info->store_mfn = diff --git a/xen-x86-consistent-nmi b/xen-x86-consistent-nmi new file mode 100644 index 0000000..2aedd0a --- /dev/null +++ b/xen-x86-consistent-nmi @@ -0,0 +1,247 @@ +From: jbeulich@novell.com +Subject: make i386 and x86 NMI code consistent, disable all APIC-related stuff +Patch-mainline: obsolete +References: 191115 + +--- sle11sp1-2010-02-09.orig/arch/x86/include/asm/irq.h 2010-02-09 16:33:59.000000000 +0100 ++++ sle11sp1-2010-02-09/arch/x86/include/asm/irq.h 2009-10-13 17:07:27.000000000 +0200 +@@ -15,7 +15,7 @@ static inline int irq_canonicalize(int i + return ((irq == 2) ? 9 : irq); + } + +-#ifdef CONFIG_X86_LOCAL_APIC ++#if defined(CONFIG_X86_LOCAL_APIC) && !defined(CONFIG_XEN) + # define ARCH_HAS_NMI_WATCHDOG + #endif + +--- sle11sp1-2010-02-09.orig/arch/x86/include/asm/nmi.h 2010-02-09 16:33:59.000000000 +0100 ++++ sle11sp1-2010-02-09/arch/x86/include/asm/nmi.h 2009-10-13 17:07:27.000000000 +0200 +@@ -5,8 +5,6 @@ + #include + #include + +-#ifdef ARCH_HAS_NMI_WATCHDOG +- + /** + * do_nmi_callback + * +@@ -16,6 +14,11 @@ + int do_nmi_callback(struct pt_regs *regs, int cpu); + + extern void die_nmi(char *str, struct pt_regs *regs, int do_panic); ++ ++extern int unknown_nmi_panic; ++ ++#ifdef ARCH_HAS_NMI_WATCHDOG ++ + extern int check_nmi_watchdog(void); + extern int nmi_watchdog_enabled; + extern int avail_to_resrv_perfctr_nmi_bit(unsigned int); +@@ -42,7 +45,6 @@ extern unsigned int nmi_watchdog; + struct ctl_table; + extern int proc_nmi_enabled(struct ctl_table *, int , + void __user *, size_t *, loff_t *); +-extern int unknown_nmi_panic; + + void arch_trigger_all_cpu_backtrace(void); + #define arch_trigger_all_cpu_backtrace arch_trigger_all_cpu_backtrace +@@ -65,7 +67,6 @@ static inline int nmi_watchdog_active(vo + */ + return nmi_watchdog & (NMI_LOCAL_APIC | NMI_IO_APIC); + } +-#endif + + void lapic_watchdog_stop(void); + int lapic_watchdog_init(unsigned nmi_hz); +@@ -73,6 +74,9 @@ int lapic_wd_event(unsigned nmi_hz); + unsigned lapic_adjust_nmi_hz(unsigned hz); + void disable_lapic_nmi_watchdog(void); + void enable_lapic_nmi_watchdog(void); ++ ++#endif ++ + void stop_nmi(void); + void restart_nmi(void); + +--- sle11sp1-2010-02-09.orig/arch/x86/kernel/apic/Makefile 2009-11-06 10:52:02.000000000 +0100 ++++ sle11sp1-2010-02-09/arch/x86/kernel/apic/Makefile 2009-10-13 17:07:27.000000000 +0200 +@@ -18,8 +18,6 @@ obj-$(CONFIG_X86_NUMAQ) += numaq_32.o + obj-$(CONFIG_X86_ES7000) += es7000_32.o + obj-$(CONFIG_X86_SUMMIT) += summit_32.o + +-obj-$(CONFIG_XEN) += nmi.o +- + probe_64-$(CONFIG_XEN) := probe_32.o + + disabled-obj-$(CONFIG_XEN) := apic_flat_$(BITS).o +--- sle11sp1-2010-02-09.orig/arch/x86/kernel/apic/nmi.c 2009-11-06 10:51:42.000000000 +0100 ++++ sle11sp1-2010-02-09/arch/x86/kernel/apic/nmi.c 2009-10-13 17:18:34.000000000 +0200 +@@ -27,8 +27,10 @@ + #include + #include + +-#ifndef CONFIG_XEN ++#ifdef ARCH_HAS_NMI_WATCHDOG + #include ++#else ++#include + #endif + #include + #include +@@ -39,6 +41,9 @@ + #include + + int unknown_nmi_panic; ++ ++#ifdef ARCH_HAS_NMI_WATCHDOG ++ + int nmi_watchdog_enabled; + + static cpumask_t backtrace_mask __read_mostly; +@@ -176,13 +181,11 @@ int __init check_nmi_watchdog(void) + kfree(prev_nmi_count); + return 0; + error: +-#ifndef CONFIG_XEN + if (nmi_watchdog == NMI_IO_APIC) { + if (!timer_through_8259) + disable_8259A_irq(0); + on_each_cpu(__acpi_nmi_disable, NULL, 1); + } +-#endif + + #ifdef CONFIG_X86_32 + timer_ack = 0; +@@ -472,8 +475,11 @@ nmi_watchdog_tick(struct pt_regs *regs, + return rc; + } + ++#endif /* ARCH_HAS_NMI_WATCHDOG */ ++ + #ifdef CONFIG_SYSCTL + ++#ifdef ARCH_HAS_NMI_WATCHDOG + static void enable_ioapic_nmi_watchdog_single(void *unused) + { + __get_cpu_var(wd_enabled) = 1; +@@ -491,6 +497,7 @@ static void disable_ioapic_nmi_watchdog( + { + on_each_cpu(stop_apic_nmi_watchdog, NULL, 1); + } ++#endif + + static int __init setup_unknown_nmi_panic(char *str) + { +@@ -509,6 +516,7 @@ static int unknown_nmi_panic_callback(st + return 0; + } + ++#ifdef ARCH_HAS_NMI_WATCHDOG + /* + * proc handler for /proc/sys/kernel/nmi + */ +@@ -546,6 +554,7 @@ int proc_nmi_enabled(struct ctl_table *t + } + return 0; + } ++#endif + + #endif /* CONFIG_SYSCTL */ + +@@ -558,6 +567,7 @@ int do_nmi_callback(struct pt_regs *regs + return 0; + } + ++#ifdef ARCH_HAS_NMI_WATCHDOG + void arch_trigger_all_cpu_backtrace(void) + { + int i; +@@ -574,3 +584,4 @@ void arch_trigger_all_cpu_backtrace(void + mdelay(1); + } + } ++#endif +--- sle11sp1-2010-02-09.orig/arch/x86/kernel/cpu/Makefile 2010-02-09 17:07:42.000000000 +0100 ++++ sle11sp1-2010-02-09/arch/x86/kernel/cpu/Makefile 2010-02-09 17:19:39.000000000 +0100 +@@ -33,7 +33,7 @@ obj-$(CONFIG_CPU_FREQ) += cpufreq/ + + obj-$(CONFIG_X86_LOCAL_APIC) += perfctr-watchdog.o + +-disabled-obj-$(CONFIG_XEN) := hypervisor.o vmware.o sched.o ++disabled-obj-$(CONFIG_XEN) := hypervisor.o vmware.o sched.o perfctr-watchdog.o + + quiet_cmd_mkcapflags = MKCAP $@ + cmd_mkcapflags = $(PERL) $(srctree)/$(src)/mkcapflags.pl $< $@ +--- sle11sp1-2010-02-09.orig/arch/x86/kernel/head-xen.c 2009-11-06 10:52:22.000000000 +0100 ++++ sle11sp1-2010-02-09/arch/x86/kernel/head-xen.c 2009-10-15 15:32:46.000000000 +0200 +@@ -179,12 +179,10 @@ void __init xen_arch_setup(void) + .address = CALLBACK_ADDR(system_call) + }; + #endif +-#if defined(CONFIG_X86_LOCAL_APIC) || defined(CONFIG_X86_32) + static const struct callback_register __initconst nmi_cb = { + .type = CALLBACKTYPE_nmi, + .address = CALLBACK_ADDR(nmi) + }; +-#endif + + ret = HYPERVISOR_callback_op(CALLBACKOP_register, &event); + if (ret == 0) +@@ -208,7 +206,6 @@ void __init xen_arch_setup(void) + #endif + BUG_ON(ret); + +-#if defined(CONFIG_X86_LOCAL_APIC) || defined(CONFIG_X86_32) + ret = HYPERVISOR_callback_op(CALLBACKOP_register, &nmi_cb); + #if CONFIG_XEN_COMPAT <= 0x030002 + if (ret == -ENOSYS) { +@@ -219,6 +216,5 @@ void __init xen_arch_setup(void) + HYPERVISOR_nmi_op(XENNMI_register_callback, &cb); + } + #endif +-#endif + } + #endif /* CONFIG_XEN */ +--- sle11sp1-2010-02-09.orig/arch/x86/kernel/traps-xen.c 2009-11-06 10:52:23.000000000 +0100 ++++ sle11sp1-2010-02-09/arch/x86/kernel/traps-xen.c 2009-10-14 17:26:48.000000000 +0200 +@@ -51,6 +51,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -394,12 +395,14 @@ static notrace __kprobes void default_do + == NOTIFY_STOP) + return; + #ifdef CONFIG_X86_LOCAL_APIC ++#ifdef ARCH_HAS_NMI_WATCHDOG + /* + * Ok, so this is none of the documented NMI sources, + * so it must be the NMI watchdog. + */ + if (nmi_watchdog_tick(regs, reason)) + return; ++#endif + if (!do_nmi_callback(regs, cpu)) + unknown_nmi_error(reason, regs); + #else +--- sle11sp1-2010-02-09.orig/kernel/sysctl.c 2009-12-16 11:47:57.000000000 +0100 ++++ sle11sp1-2010-02-09/kernel/sysctl.c 2009-12-16 12:15:35.000000000 +0100 +@@ -790,6 +790,7 @@ static struct ctl_table kern_table[] = { + .mode = 0644, + .proc_handler = &proc_dointvec, + }, ++#ifdef ARCH_HAS_NMI_WATCHDOG + { + .procname = "nmi_watchdog", + .data = &nmi_watchdog_enabled, +@@ -798,6 +799,7 @@ static struct ctl_table kern_table[] = { + .proc_handler = &proc_nmi_enabled, + }, + #endif ++#endif + #if defined(CONFIG_X86) + { + .ctl_name = KERN_PANIC_ON_NMI, diff --git a/xen-x86-dcr-fallback b/xen-x86-dcr-fallback new file mode 100644 index 0000000..0238c51 --- /dev/null +++ b/xen-x86-dcr-fallback @@ -0,0 +1,168 @@ +Subject: Add fallback when XENMEM_exchange fails to replace contiguous region +From: jbeulich@novell.com +Patch-mainline: obsolete +References: 181869 + +This avoids losing precious special memory in places where any memory can be +used. + +--- sle11sp1-2010-03-29.orig/arch/x86/mm/hypervisor.c 2009-11-06 10:52:02.000000000 +0100 ++++ sle11sp1-2010-03-29/arch/x86/mm/hypervisor.c 2009-06-09 15:52:17.000000000 +0200 +@@ -43,6 +43,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -719,6 +720,83 @@ void xen_destroy_contiguous_region(unsig + BUG(); + + balloon_unlock(flags); ++ ++ if (unlikely(!success)) { ++ /* Try hard to get the special memory back to Xen. */ ++ exchange.in.extent_order = 0; ++ set_xen_guest_handle(exchange.in.extent_start, &in_frame); ++ ++ for (i = 0; i < (1U<> PAGE_SHIFT; ++ set_phys_to_machine(pfn, frame); ++ if (!xen_feature(XENFEAT_auto_translated_physmap)) { ++ mmu.ptr = ((uint64_t)frame << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE; ++ mmu.val = pfn; ++ cr_mcl[j].op = __HYPERVISOR_mmu_update; ++ cr_mcl[j].args[0] = (unsigned long)&mmu; ++ cr_mcl[j].args[1] = 1; ++ cr_mcl[j].args[2] = 0; ++ cr_mcl[j].args[3] = DOMID_SELF; ++ ++j; ++ } ++ ++ cr_mcl[j].op = __HYPERVISOR_memory_op; ++ cr_mcl[j].args[0] = XENMEM_decrease_reservation; ++ cr_mcl[j].args[1] = (unsigned long)&exchange.in; ++ ++ if (HYPERVISOR_multicall(cr_mcl, j + 1)) ++ BUG(); ++ BUG_ON(cr_mcl[j].result != 1); ++ while (j--) ++ BUG_ON(cr_mcl[j].result != 0); ++ ++ balloon_unlock(flags); ++ ++ free_empty_pages(&page, 1); ++ ++ in_frame++; ++ vstart += PAGE_SIZE; ++ } ++ } + } + EXPORT_SYMBOL_GPL(xen_destroy_contiguous_region); + +--- sle11sp1-2010-03-29.orig/drivers/xen/balloon/balloon.c 2010-03-31 10:00:17.000000000 +0200 ++++ sle11sp1-2010-03-29/drivers/xen/balloon/balloon.c 2010-03-31 10:00:24.000000000 +0200 +@@ -776,7 +776,11 @@ struct page **alloc_empty_pages_and_page + } + EXPORT_SYMBOL_GPL(alloc_empty_pages_and_pagevec); + +-void free_empty_pages_and_pagevec(struct page **pagevec, int nr_pages) ++#endif /* CONFIG_XEN_BACKEND */ ++ ++#ifdef CONFIG_XEN ++static void _free_empty_pages_and_pagevec(struct page **pagevec, int nr_pages, ++ bool free_vec) + { + unsigned long flags; + int i; +@@ -787,17 +791,33 @@ void free_empty_pages_and_pagevec(struct + balloon_lock(flags); + for (i = 0; i < nr_pages; i++) { + BUG_ON(page_count(pagevec[i]) != 1); +- balloon_append(pagevec[i], 0); ++ balloon_append(pagevec[i], !free_vec); ++ } ++ if (!free_vec) { ++ bs.current_pages -= nr_pages; ++ totalram_pages = bs.current_pages - totalram_bias; + } + balloon_unlock(flags); + +- kfree(pagevec); ++ if (free_vec) ++ kfree(pagevec); + + schedule_work(&balloon_worker); + } +-EXPORT_SYMBOL_GPL(free_empty_pages_and_pagevec); + +-#endif /* CONFIG_XEN_BACKEND */ ++void free_empty_pages(struct page **pagevec, int nr_pages) ++{ ++ _free_empty_pages_and_pagevec(pagevec, nr_pages, false); ++} ++#endif ++ ++#if defined(CONFIG_XEN_BACKEND) || defined(CONFIG_XEN_BACKEND_MODULE) ++void free_empty_pages_and_pagevec(struct page **pagevec, int nr_pages) ++{ ++ _free_empty_pages_and_pagevec(pagevec, nr_pages, true); ++} ++EXPORT_SYMBOL_GPL(free_empty_pages_and_pagevec); ++#endif + + void balloon_release_driver_page(struct page *page) + { +--- sle11sp1-2010-03-29.orig/include/xen/balloon.h 2009-11-06 10:51:32.000000000 +0100 ++++ sle11sp1-2010-03-29/include/xen/balloon.h 2009-06-09 15:52:17.000000000 +0200 +@@ -47,6 +47,10 @@ void balloon_update_driver_allowance(lon + struct page **alloc_empty_pages_and_pagevec(int nr_pages); + void free_empty_pages_and_pagevec(struct page **pagevec, int nr_pages); + ++/* Free an empty page range (not allocated through ++ alloc_empty_pages_and_pagevec), adding to the balloon. */ ++void free_empty_pages(struct page **pagevec, int nr_pages); ++ + void balloon_release_driver_page(struct page *page); + + /* diff --git a/xen-x86-exit-mmap b/xen-x86-exit-mmap new file mode 100644 index 0000000..94e4cc2 --- /dev/null +++ b/xen-x86-exit-mmap @@ -0,0 +1,72 @@ +Subject: be more aggressive about de-activating mm-s under destruction +From: jbeulich@novell.com +Patch-mainline: obsolete + +... by not only handling the current task on the CPU arch_exit_mmap() +gets executed on, but also forcing remote CPUs to do so. + +--- sle11sp1-2010-03-22.orig/arch/x86/mm/pgtable-xen.c 2010-03-22 12:59:39.000000000 +0100 ++++ sle11sp1-2010-03-22/arch/x86/mm/pgtable-xen.c 2010-03-22 12:59:47.000000000 +0100 +@@ -1,5 +1,6 @@ + #include + #include ++#include + #include + #include + #include +@@ -437,27 +438,44 @@ void arch_dup_mmap(struct mm_struct *old + mm_pin(mm); + } + +-void arch_exit_mmap(struct mm_struct *mm) ++/* ++ * We aggressively remove defunct pgd from cr3. We execute unmap_vmas() *much* ++ * faster this way, as no hypercalls are needed for the page table updates. ++ */ ++static void leave_active_mm(struct task_struct *tsk, struct mm_struct *mm) ++ __releases(tsk->alloc_lock) + { +- struct task_struct *tsk = current; +- +- task_lock(tsk); +- +- /* +- * We aggressively remove defunct pgd from cr3. We execute unmap_vmas() +- * *much* faster this way, as no tlb flushes means bigger wrpt batches. +- */ + if (tsk->active_mm == mm) { + tsk->active_mm = &init_mm; + atomic_inc(&init_mm.mm_count); + + switch_mm(mm, &init_mm, tsk); + +- atomic_dec(&mm->mm_count); +- BUG_ON(atomic_read(&mm->mm_count) == 0); ++ if (atomic_dec_and_test(&mm->mm_count)) ++ BUG(); + } + + task_unlock(tsk); ++} ++ ++static void _leave_active_mm(void *mm) ++{ ++ struct task_struct *tsk = current; ++ ++ if (spin_trylock(&tsk->alloc_lock)) ++ leave_active_mm(tsk, mm); ++} ++ ++void arch_exit_mmap(struct mm_struct *mm) ++{ ++ struct task_struct *tsk = current; ++ ++ task_lock(tsk); ++ leave_active_mm(tsk, mm); ++ ++ preempt_disable(); ++ smp_call_function_many(mm_cpumask(mm), _leave_active_mm, mm, 1); ++ preempt_enable(); + + if (PagePinned(virt_to_page(mm->pgd)) + && atomic_read(&mm->mm_count) == 1 diff --git a/xen-x86-machphys-prediction b/xen-x86-machphys-prediction new file mode 100644 index 0000000..b633164 --- /dev/null +++ b/xen-x86-machphys-prediction @@ -0,0 +1,204 @@ +From: jbeulich@novell.com +Subject: properly predict phys<->mach translations +Patch-mainline: obsolete + +--- head-2009-07-28.orig/arch/x86/include/mach-xen/asm/maddr_32.h 2009-07-28 12:14:16.000000000 +0200 ++++ head-2009-07-28/arch/x86/include/mach-xen/asm/maddr_32.h 2009-07-29 10:56:35.000000000 +0200 +@@ -30,17 +30,19 @@ extern unsigned int machine_to_phys_or + + static inline unsigned long pfn_to_mfn(unsigned long pfn) + { +- if (xen_feature(XENFEAT_auto_translated_physmap)) ++ if (unlikely(xen_feature(XENFEAT_auto_translated_physmap))) + return pfn; +- BUG_ON(max_mapnr && pfn >= max_mapnr); ++ if (likely(max_mapnr)) ++ BUG_ON(pfn >= max_mapnr); + return phys_to_machine_mapping[pfn] & ~FOREIGN_FRAME_BIT; + } + + static inline int phys_to_machine_mapping_valid(unsigned long pfn) + { +- if (xen_feature(XENFEAT_auto_translated_physmap)) ++ if (unlikely(xen_feature(XENFEAT_auto_translated_physmap))) + return 1; +- BUG_ON(max_mapnr && pfn >= max_mapnr); ++ if (likely(max_mapnr)) ++ BUG_ON(pfn >= max_mapnr); + return (phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY); + } + +@@ -48,7 +50,7 @@ static inline unsigned long mfn_to_pfn(u + { + unsigned long pfn; + +- if (xen_feature(XENFEAT_auto_translated_physmap)) ++ if (unlikely(xen_feature(XENFEAT_auto_translated_physmap))) + return mfn; + + if (unlikely((mfn >> machine_to_phys_order) != 0)) +@@ -95,17 +97,18 @@ static inline unsigned long mfn_to_pfn(u + static inline unsigned long mfn_to_local_pfn(unsigned long mfn) + { + unsigned long pfn = mfn_to_pfn(mfn); +- if ((pfn < max_mapnr) +- && !xen_feature(XENFEAT_auto_translated_physmap) +- && (phys_to_machine_mapping[pfn] != mfn)) ++ if (likely(pfn < max_mapnr) ++ && likely(!xen_feature(XENFEAT_auto_translated_physmap)) ++ && unlikely(phys_to_machine_mapping[pfn] != mfn)) + return max_mapnr; /* force !pfn_valid() */ + return pfn; + } + + static inline void set_phys_to_machine(unsigned long pfn, unsigned long mfn) + { +- BUG_ON(max_mapnr && pfn >= max_mapnr); +- if (xen_feature(XENFEAT_auto_translated_physmap)) { ++ if (likely(max_mapnr)) ++ BUG_ON(pfn >= max_mapnr); ++ if (unlikely(xen_feature(XENFEAT_auto_translated_physmap))) { + BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY); + return; + } +--- head-2009-07-28.orig/arch/x86/include/mach-xen/asm/maddr_64.h 2009-07-28 12:14:16.000000000 +0200 ++++ head-2009-07-28/arch/x86/include/mach-xen/asm/maddr_64.h 2009-07-29 10:56:35.000000000 +0200 +@@ -25,17 +25,19 @@ extern unsigned int machine_to_phys_or + + static inline unsigned long pfn_to_mfn(unsigned long pfn) + { +- if (xen_feature(XENFEAT_auto_translated_physmap)) ++ if (unlikely(xen_feature(XENFEAT_auto_translated_physmap))) + return pfn; +- BUG_ON(max_mapnr && pfn >= max_mapnr); ++ if (likely(max_mapnr)) ++ BUG_ON(pfn >= max_mapnr); + return phys_to_machine_mapping[pfn] & ~FOREIGN_FRAME_BIT; + } + + static inline int phys_to_machine_mapping_valid(unsigned long pfn) + { +- if (xen_feature(XENFEAT_auto_translated_physmap)) ++ if (unlikely(xen_feature(XENFEAT_auto_translated_physmap))) + return 1; +- BUG_ON(max_mapnr && pfn >= max_mapnr); ++ if (likely(max_mapnr)) ++ BUG_ON(pfn >= max_mapnr); + return (phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY); + } + +@@ -43,7 +45,7 @@ static inline unsigned long mfn_to_pfn(u + { + unsigned long pfn; + +- if (xen_feature(XENFEAT_auto_translated_physmap)) ++ if (unlikely(xen_feature(XENFEAT_auto_translated_physmap))) + return mfn; + + if (unlikely((mfn >> machine_to_phys_order) != 0)) +@@ -90,17 +92,18 @@ static inline unsigned long mfn_to_pfn(u + static inline unsigned long mfn_to_local_pfn(unsigned long mfn) + { + unsigned long pfn = mfn_to_pfn(mfn); +- if ((pfn < max_mapnr) +- && !xen_feature(XENFEAT_auto_translated_physmap) +- && (phys_to_machine_mapping[pfn] != mfn)) ++ if (likely(pfn < max_mapnr) ++ && likely(!xen_feature(XENFEAT_auto_translated_physmap)) ++ && unlikely(phys_to_machine_mapping[pfn] != mfn)) + return max_mapnr; /* force !pfn_valid() */ + return pfn; + } + + static inline void set_phys_to_machine(unsigned long pfn, unsigned long mfn) + { +- BUG_ON(max_mapnr && pfn >= max_mapnr); +- if (xen_feature(XENFEAT_auto_translated_physmap)) { ++ if (likely(max_mapnr)) ++ BUG_ON(pfn >= max_mapnr); ++ if (unlikely(xen_feature(XENFEAT_auto_translated_physmap))) { + BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY); + return; + } +--- head-2009-07-28.orig/arch/x86/include/mach-xen/asm/pgtable_types.h 2009-07-28 13:14:11.000000000 +0200 ++++ head-2009-07-28/arch/x86/include/mach-xen/asm/pgtable_types.h 2009-07-29 10:56:35.000000000 +0200 +@@ -207,7 +207,7 @@ typedef struct { pgdval_t pgd; } pgd_t; + #define __pgd_ma(x) ((pgd_t) { (x) } ) + static inline pgd_t xen_make_pgd(pgdval_t val) + { +- if (val & _PAGE_PRESENT) ++ if (likely(val & _PAGE_PRESENT)) + val = pte_phys_to_machine(val); + return (pgd_t) { val }; + } +@@ -217,10 +217,10 @@ static inline pgdval_t xen_pgd_val(pgd_t + { + pgdval_t ret = __pgd_val(pgd); + #if PAGETABLE_LEVELS == 2 && CONFIG_XEN_COMPAT <= 0x030002 +- if (ret) ++ if (likely(ret)) + ret = machine_to_phys(ret) | _PAGE_PRESENT; + #else +- if (ret & _PAGE_PRESENT) ++ if (likely(ret & _PAGE_PRESENT)) + ret = pte_machine_to_phys(ret); + #endif + return ret; +@@ -237,7 +237,7 @@ typedef struct { pudval_t pud; } pud_t; + #define __pud_ma(x) ((pud_t) { (x) } ) + static inline pud_t xen_make_pud(pudval_t val) + { +- if (val & _PAGE_PRESENT) ++ if (likely(val & _PAGE_PRESENT)) + val = pte_phys_to_machine(val); + return (pud_t) { val }; + } +@@ -246,7 +246,7 @@ static inline pud_t xen_make_pud(pudval_ + static inline pudval_t xen_pud_val(pud_t pud) + { + pudval_t ret = __pud_val(pud); +- if (ret & _PAGE_PRESENT) ++ if (likely(ret & _PAGE_PRESENT)) + ret = pte_machine_to_phys(ret); + return ret; + } +@@ -266,7 +266,7 @@ typedef struct { pmdval_t pmd; } pmd_t; + #define __pmd_ma(x) ((pmd_t) { (x) } ) + static inline pmd_t xen_make_pmd(pmdval_t val) + { +- if (val & _PAGE_PRESENT) ++ if (likely(val & _PAGE_PRESENT)) + val = pte_phys_to_machine(val); + return (pmd_t) { val }; + } +@@ -276,10 +276,10 @@ static inline pmdval_t xen_pmd_val(pmd_t + { + pmdval_t ret = __pmd_val(pmd); + #if CONFIG_XEN_COMPAT <= 0x030002 +- if (ret) ++ if (likely(ret)) + ret = pte_machine_to_phys(ret) | _PAGE_PRESENT; + #else +- if (ret & _PAGE_PRESENT) ++ if (likely(ret & _PAGE_PRESENT)) + ret = pte_machine_to_phys(ret); + #endif + return ret; +@@ -308,7 +308,7 @@ static inline pmdval_t pmd_flags(pmd_t p + #define __pte_ma(x) ((pte_t) { .pte = (x) } ) + static inline pte_t xen_make_pte(pteval_t val) + { +- if ((val & (_PAGE_PRESENT|_PAGE_IOMAP)) == _PAGE_PRESENT) ++ if (likely((val & (_PAGE_PRESENT|_PAGE_IOMAP)) == _PAGE_PRESENT)) + val = pte_phys_to_machine(val); + return (pte_t) { .pte = val }; + } +@@ -317,7 +317,7 @@ static inline pte_t xen_make_pte(pteval_ + static inline pteval_t xen_pte_val(pte_t pte) + { + pteval_t ret = __pte_val(pte); +- if ((pte.pte_low & (_PAGE_PRESENT|_PAGE_IOMAP)) == _PAGE_PRESENT) ++ if (likely((pte.pte_low & (_PAGE_PRESENT|_PAGE_IOMAP)) == _PAGE_PRESENT)) + ret = pte_machine_to_phys(ret); + return ret; + } diff --git a/xen-x86-no-lapic b/xen-x86-no-lapic new file mode 100644 index 0000000..b9a8cac --- /dev/null +++ b/xen-x86-no-lapic @@ -0,0 +1,374 @@ +From: jbeulich@novell.com +Subject: Disallow all accesses to the local APIC page +Patch-mainline: obsolete +References: 191115 + +--- sle11sp1-2010-03-22.orig/arch/x86/include/asm/apic.h 2009-12-04 10:44:45.000000000 +0100 ++++ sle11sp1-2010-03-22/arch/x86/include/asm/apic.h 2009-10-13 17:19:31.000000000 +0200 +@@ -10,7 +10,9 @@ + #include + #include + #include ++#ifndef CONFIG_XEN + #include ++#endif + #include + #include + #include +@@ -49,6 +51,7 @@ static inline void generic_apic_probe(vo + #ifdef CONFIG_X86_LOCAL_APIC + + extern unsigned int apic_verbosity; ++#ifndef CONFIG_XEN + extern int local_apic_timer_c2_ok; + + extern int disable_apic; +@@ -121,6 +124,8 @@ extern u64 native_apic_icr_read(void); + + extern int x2apic_mode; + ++#endif /* CONFIG_XEN */ ++ + #ifdef CONFIG_X86_X2APIC + /* + * Make previous memory operations globally visible before +@@ -367,6 +372,8 @@ struct apic { + */ + extern struct apic *apic; + ++#ifndef CONFIG_XEN ++ + /* + * APIC functionality to boot other CPUs - only used on SMP: + */ +@@ -460,6 +467,8 @@ static inline void default_wait_for_init + + extern void generic_bigsmp_probe(void); + ++#endif /* CONFIG_XEN */ ++ + + #ifdef CONFIG_X86_LOCAL_APIC + +@@ -479,6 +488,8 @@ static inline const struct cpumask *defa + DECLARE_EARLY_PER_CPU(u16, x86_bios_cpu_apicid); + + ++#ifndef CONFIG_XEN ++ + static inline unsigned int read_apic_id(void) + { + unsigned int reg; +@@ -590,6 +601,8 @@ static inline physid_mask_t default_apic + return physid_mask_of_physid(phys_apicid); + } + ++#endif /* CONFIG_XEN */ ++ + #endif /* CONFIG_X86_LOCAL_APIC */ + + #ifdef CONFIG_X86_32 +--- sle11sp1-2010-03-22.orig/arch/x86/include/asm/apicdef.h 2010-03-22 12:07:53.000000000 +0100 ++++ sle11sp1-2010-03-22/arch/x86/include/asm/apicdef.h 2009-10-14 17:01:50.000000000 +0200 +@@ -11,6 +11,8 @@ + #define IO_APIC_DEFAULT_PHYS_BASE 0xfec00000 + #define APIC_DEFAULT_PHYS_BASE 0xfee00000 + ++#ifndef CONFIG_XEN ++ + #define APIC_ID 0x20 + + #define APIC_LVR 0x30 +@@ -136,6 +138,16 @@ + #define APIC_BASE_MSR 0x800 + #define X2APIC_ENABLE (1UL << 10) + ++#else /* CONFIG_XEN */ ++ ++enum { ++ APIC_DEST_ALLBUT = 0x1, ++ APIC_DEST_SELF, ++ APIC_DEST_ALLINC ++}; ++ ++#endif /* CONFIG_XEN */ ++ + #ifdef CONFIG_X86_32 + # define MAX_IO_APICS 64 + #else +@@ -143,6 +155,8 @@ + # define MAX_LOCAL_APIC 32768 + #endif + ++#ifndef CONFIG_XEN ++ + /* + * All x86-64 systems are xAPIC compatible. + * In the following, "apicid" is a physical APIC ID. +@@ -413,6 +427,8 @@ struct local_apic { + + #undef u32 + ++#endif /* CONFIG_XEN */ ++ + #ifdef CONFIG_X86_32 + #define BAD_APICID 0xFFu + #else +--- sle11sp1-2010-03-22.orig/arch/x86/include/mach-xen/asm/fixmap.h 2009-11-06 10:52:22.000000000 +0100 ++++ sle11sp1-2010-03-22/arch/x86/include/mach-xen/asm/fixmap.h 2009-10-13 17:19:31.000000000 +0200 +@@ -17,7 +17,6 @@ + #ifndef __ASSEMBLY__ + #include + #include +-#include + #include + #ifdef CONFIG_X86_32 + #include +@@ -82,10 +81,10 @@ enum fixed_addresses { + #endif + FIX_DBGP_BASE, + FIX_EARLYCON_MEM_BASE, ++#ifndef CONFIG_XEN + #ifdef CONFIG_X86_LOCAL_APIC + FIX_APIC_BASE, /* local (CPU) APIC) -- required for SMP or not */ + #endif +-#ifndef CONFIG_XEN + #ifdef CONFIG_X86_IO_APIC + FIX_IO_APIC_BASE_0, + FIX_IO_APIC_BASE_END = FIX_IO_APIC_BASE_0 + MAX_IO_APICS - 1, +--- sle11sp1-2010-03-22.orig/arch/x86/include/mach-xen/asm/smp.h 2009-11-20 11:18:10.000000000 +0100 ++++ sle11sp1-2010-03-22/arch/x86/include/mach-xen/asm/smp.h 2009-11-20 11:20:18.000000000 +0100 +@@ -15,7 +15,7 @@ + # include + # endif + #endif +-#include ++#include + #include + + extern int smp_num_siblings; +@@ -168,7 +168,7 @@ extern unsigned disabled_cpus __cpuinitd + + #include + +-#ifdef CONFIG_X86_LOCAL_APIC ++#if defined(CONFIG_X86_LOCAL_APIC) && !defined(CONFIG_XEN) + + #ifndef CONFIG_X86_64 + static inline int logical_smp_processor_id(void) +--- sle11sp1-2010-03-22.orig/arch/x86/kernel/acpi/boot.c 2010-02-17 14:50:55.000000000 +0100 ++++ sle11sp1-2010-03-22/arch/x86/kernel/acpi/boot.c 2010-02-18 15:30:28.000000000 +0100 +@@ -72,13 +72,13 @@ int acpi_sci_override_gsi __initdata; + #ifndef CONFIG_XEN + int acpi_skip_timer_override __initdata; + int acpi_use_timer_override __initdata; +-#else +-#define acpi_skip_timer_override 0 +-#endif + + #ifdef CONFIG_X86_LOCAL_APIC + static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE; + #endif ++#else ++#define acpi_skip_timer_override 0 ++#endif + + #ifndef __HAVE_ARCH_CMPXCHG + #warning ACPI uses CMPXCHG, i486 and later hardware +@@ -137,6 +137,7 @@ static int __init acpi_parse_madt(struct + return -ENODEV; + } + ++#ifndef CONFIG_XEN + if (madt->address) { + acpi_lapic_addr = (u64) madt->address; + +@@ -144,7 +145,6 @@ static int __init acpi_parse_madt(struct + madt->address); + } + +-#ifndef CONFIG_XEN + default_acpi_madt_oem_check(madt->header.oem_id, + madt->header.oem_table_id); + #endif +@@ -245,6 +245,7 @@ static int __init + acpi_parse_lapic_addr_ovr(struct acpi_subtable_header * header, + const unsigned long end) + { ++#ifndef CONFIG_XEN + struct acpi_madt_local_apic_override *lapic_addr_ovr = NULL; + + lapic_addr_ovr = (struct acpi_madt_local_apic_override *)header; +@@ -253,6 +254,7 @@ acpi_parse_lapic_addr_ovr(struct acpi_su + return -EINVAL; + + acpi_lapic_addr = lapic_addr_ovr->address; ++#endif + + return 0; + } +@@ -1089,7 +1091,7 @@ int mp_register_gsi(struct device *dev, + + ioapic_pin = mp_find_ioapic_pin(ioapic, gsi); + +-#ifdef CONFIG_X86_32 ++#if defined(CONFIG_X86_32) && !defined(CONFIG_XEN) + if (ioapic_renumber_irq) + gsi = ioapic_renumber_irq(ioapic, gsi); + #endif +--- sle11sp1-2010-03-22.orig/arch/x86/kernel/apic/io_apic-xen.c 2010-03-22 12:52:03.000000000 +0100 ++++ sle11sp1-2010-03-22/arch/x86/kernel/apic/io_apic-xen.c 2010-03-22 12:59:10.000000000 +0100 +@@ -1093,7 +1093,9 @@ static inline int irq_trigger(int idx) + return MPBIOS_trigger(idx); + } + ++#ifndef CONFIG_XEN + int (*ioapic_renumber_irq)(int ioapic, int irq); ++#endif + static int pin_2_irq(int idx, int apic, int pin) + { + int irq, i; +@@ -1115,11 +1117,13 @@ static int pin_2_irq(int idx, int apic, + while (i < apic) + irq += nr_ioapic_registers[i++]; + irq += pin; ++#ifndef CONFIG_XEN + /* + * For MPS mode, so far only needed by ES7000 platform + */ + if (ioapic_renumber_irq) + irq = ioapic_renumber_irq(apic, irq); ++#endif + } + + #ifdef CONFIG_X86_32 +@@ -4068,10 +4072,12 @@ int io_apic_set_pci_routing(struct devic + u8 __init io_apic_unique_id(u8 id) + { + #ifdef CONFIG_X86_32 ++#ifndef CONFIG_XEN + if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && + !APIC_XAPIC(apic_version[boot_cpu_physical_apicid])) + return io_apic_get_unique_id(nr_ioapics, id); + else ++#endif + return id; + #else + int i; +--- sle11sp1-2010-03-22.orig/arch/x86/kernel/irq-xen.c 2010-01-07 11:22:50.000000000 +0100 ++++ sle11sp1-2010-03-22/arch/x86/kernel/irq-xen.c 2009-12-18 10:14:24.000000000 +0100 +@@ -15,9 +15,9 @@ + #include + #include + ++#ifndef CONFIG_XEN + atomic_t irq_err_count; + +-#ifndef CONFIG_XEN + /* Function pointer for generic interrupt vector handling */ + void (*generic_interrupt_extension)(void) = NULL; + #endif +@@ -57,7 +57,7 @@ static int show_other_interrupts(struct + for_each_online_cpu(j) + seq_printf(p, "%10u ", irq_stats(j)->__nmi_count); + seq_printf(p, " Non-maskable interrupts\n"); +-#ifdef CONFIG_X86_LOCAL_APIC ++#if defined(CONFIG_X86_LOCAL_APIC) && !defined(CONFIG_XEN) + seq_printf(p, "%*s: ", prec, "LOC"); + for_each_online_cpu(j) + seq_printf(p, "%10u ", irq_stats(j)->apic_timer_irqs); +@@ -122,10 +122,12 @@ static int show_other_interrupts(struct + seq_printf(p, "%10u ", per_cpu(mce_poll_count, j)); + seq_printf(p, " Machine check polls\n"); + #endif ++#ifndef CONFIG_XEN + seq_printf(p, "%*s: %10u\n", prec, "ERR", atomic_read(&irq_err_count)); + #if defined(CONFIG_X86_IO_APIC) + seq_printf(p, "%*s: %10u\n", prec, "MIS", atomic_read(&irq_mis_count)); + #endif ++#endif + return 0; + } + +@@ -221,12 +223,16 @@ u64 arch_irq_stat_cpu(unsigned int cpu) + + u64 arch_irq_stat(void) + { ++#ifndef CONFIG_XEN + u64 sum = atomic_read(&irq_err_count); + + #ifdef CONFIG_X86_IO_APIC + sum += atomic_read(&irq_mis_count); + #endif + return sum; ++#else ++ return 0; ++#endif + } + + +--- sle11sp1-2010-03-22.orig/arch/x86/kernel/mpparse-xen.c 2010-03-01 14:45:20.000000000 +0100 ++++ sle11sp1-2010-03-22/arch/x86/kernel/mpparse-xen.c 2010-03-01 14:47:29.000000000 +0100 +@@ -288,7 +288,9 @@ static int __init smp_check_mpc(struct m + + printk(KERN_INFO "MPTABLE: Product ID: %s\n", str); + ++#ifndef CONFIG_XEN + printk(KERN_INFO "MPTABLE: APIC at: 0x%X\n", mpc->lapic); ++#endif + + return 1; + } +@@ -320,12 +322,14 @@ static int __init smp_read_mpc(struct mp + if (!smp_check_mpc(mpc, oem, str)) + return 0; + +-#if defined(CONFIG_X86_32) && !defined(CONFIG_XEN) ++#ifndef CONFIG_XEN ++#ifdef CONFIG_X86_32 + generic_mps_oem_check(mpc, oem, str); + #endif + /* save the local APIC address, it might be non-default */ + if (!acpi_lapic) + mp_lapic_addr = mpc->lapic; ++#endif + + if (early) + return 1; +@@ -512,10 +516,12 @@ static inline void __init construct_defa + int linttypes[2] = { mp_ExtINT, mp_NMI }; + int i; + ++#ifndef CONFIG_XEN + /* + * local APIC has default address + */ + mp_lapic_addr = APIC_DEFAULT_PHYS_BASE; ++#endif + + /* + * 2 CPUs, numbered 0 & 1. +@@ -648,10 +654,12 @@ void __init default_get_smp_config(unsig + */ + if (mpf->feature1 != 0) { + if (early) { ++#ifndef CONFIG_XEN + /* + * local APIC has default address + */ + mp_lapic_addr = APIC_DEFAULT_PHYS_BASE; ++#endif + return; + } + +--- sle11sp1-2010-03-22.orig/drivers/xen/core/smpboot.c 2010-03-22 12:57:50.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/xen/core/smpboot.c 2010-03-22 12:59:04.000000000 +0100 +@@ -362,7 +362,7 @@ void __init smp_prepare_cpus(unsigned in + * Here we can be sure that there is an IO-APIC in the system. Let's + * go and set it up: + */ +- if (!skip_ioapic_setup && nr_ioapics) ++ if (cpu_has_apic && !skip_ioapic_setup && nr_ioapics) + setup_IO_APIC(); + #endif + } diff --git a/xen-x86-panic-no-reboot b/xen-x86-panic-no-reboot new file mode 100644 index 0000000..a29d6f4 --- /dev/null +++ b/xen-x86-panic-no-reboot @@ -0,0 +1,32 @@ +From: jbeulich@novell.com +Subject: Don't automatically reboot Dom0 on panic (match native) +Patch-mainline: obsolete + +$subject says it all. + +--- sle11sp1-2010-02-09.orig/arch/x86/kernel/setup-xen.c 2010-02-09 17:12:56.000000000 +0100 ++++ sle11sp1-2010-02-09/arch/x86/kernel/setup-xen.c 2010-02-09 17:19:30.000000000 +0100 +@@ -781,15 +781,17 @@ void __init setup_arch(char **cmdline_p) + unsigned long p2m_pages; + struct physdev_set_iopl set_iopl; + ++ if (!is_initial_xendomain()) { + #ifdef CONFIG_X86_32 +- /* Force a quick death if the kernel panics (not domain 0). */ +- extern int panic_timeout; +- if (!panic_timeout && !is_initial_xendomain()) +- panic_timeout = 1; ++ /* Force a quick death if the kernel panics (not domain 0). */ ++ extern int panic_timeout; ++ if (!panic_timeout) ++ panic_timeout = 1; + #endif + +- /* Register a call for panic conditions. */ +- atomic_notifier_chain_register(&panic_notifier_list, &xen_panic_block); ++ /* Register a call for panic conditions. */ ++ atomic_notifier_chain_register(&panic_notifier_list, &xen_panic_block); ++ } + #endif /* CONFIG_XEN */ + + #ifdef CONFIG_X86_32 diff --git a/xen-x86-per-cpu-vcpu-info b/xen-x86-per-cpu-vcpu-info new file mode 100644 index 0000000..93884fa --- /dev/null +++ b/xen-x86-per-cpu-vcpu-info @@ -0,0 +1,638 @@ +From: jbeulich@novell.com +Subject: x86: use per-cpu storage for shared vcpu_info structure +Patch-mainline: obsolete + +... reducing access code size and latency, as well as being the +prerequisite for removing the limitation on 32 vCPU-s per guest. + +--- sle11sp1-2010-03-29.orig/arch/x86/include/asm/percpu.h 2010-03-29 09:00:34.000000000 +0200 ++++ sle11sp1-2010-03-29/arch/x86/include/asm/percpu.h 2009-11-06 11:12:01.000000000 +0100 +@@ -133,6 +133,38 @@ do { \ + ret__; \ + }) + ++#define percpu_xchg_op(op, var, val) \ ++({ \ ++ typedef typeof(var) T__; \ ++ T__ ret__; \ ++ if (0) \ ++ ret__ = (val); \ ++ switch (sizeof(var)) { \ ++ case 1: \ ++ asm(op "b %0,"__percpu_arg(1) \ ++ : "=q" (ret__), "+m" (var) \ ++ : "0" ((T__)(val))); \ ++ break; \ ++ case 2: \ ++ asm(op "w %0,"__percpu_arg(1) \ ++ : "=r" (ret__), "+m" (var) \ ++ : "0" ((T__)(val))); \ ++ break; \ ++ case 4: \ ++ asm(op "l %0,"__percpu_arg(1) \ ++ : "=r" (ret__), "+m" (var) \ ++ : "0" ((T__)(val))); \ ++ break; \ ++ case 8: \ ++ asm(op "q %0,"__percpu_arg(1) \ ++ : "=r" (ret__), "+m" (var) \ ++ : "0" ((T__)(val))); \ ++ break; \ ++ default: __bad_percpu_size(); \ ++ } \ ++ ret__; \ ++}) ++ + /* + * percpu_read() makes gcc load the percpu variable every time it is + * accessed while percpu_read_stable() allows the value to be cached. +@@ -152,6 +184,10 @@ do { \ + #define percpu_and(var, val) percpu_to_op("and", per_cpu__##var, val) + #define percpu_or(var, val) percpu_to_op("or", per_cpu__##var, val) + #define percpu_xor(var, val) percpu_to_op("xor", per_cpu__##var, val) ++#define percpu_xchg(var, val) percpu_xchg_op("xchg", per_cpu__##var, val) ++#if defined(CONFIG_X86_XADD) || defined(CONFIG_X86_64) ++#define percpu_xadd(var, val) percpu_xchg_op("xadd", per_cpu__##var, val) ++#endif + + /* This is not atomic against other CPUs -- CPU preemption needs to be off */ + #define x86_test_and_clear_bit_percpu(bit, var) \ +--- sle11sp1-2010-03-29.orig/arch/x86/include/mach-xen/asm/hypervisor.h 2009-11-23 10:49:39.000000000 +0100 ++++ sle11sp1-2010-03-29/arch/x86/include/mach-xen/asm/hypervisor.h 2009-11-23 10:53:45.000000000 +0100 +@@ -50,12 +50,26 @@ + + extern shared_info_t *HYPERVISOR_shared_info; + ++#ifdef CONFIG_XEN_VCPU_INFO_PLACEMENT ++DECLARE_PER_CPU(struct vcpu_info, vcpu_info); ++#define vcpu_info(cpu) (&per_cpu(vcpu_info, cpu)) ++#define current_vcpu_info() (&__get_cpu_var(vcpu_info)) ++#define vcpu_info_read(fld) percpu_read(vcpu_info.fld) ++#define vcpu_info_write(fld, val) percpu_write(vcpu_info.fld, val) ++#define vcpu_info_xchg(fld, val) percpu_xchg(vcpu_info.fld, val) ++void setup_vcpu_info(unsigned int cpu); ++void adjust_boot_vcpu_info(void); ++#else + #define vcpu_info(cpu) (HYPERVISOR_shared_info->vcpu_info + (cpu)) + #ifdef CONFIG_SMP + #define current_vcpu_info() vcpu_info(smp_processor_id()) + #else + #define current_vcpu_info() vcpu_info(0) + #endif ++#define vcpu_info_read(fld) (current_vcpu_info()->fld) ++#define vcpu_info_write(fld, val) (current_vcpu_info()->fld = (val)) ++static inline void setup_vcpu_info(unsigned int cpu) {} ++#endif + + #ifdef CONFIG_X86_32 + extern unsigned long hypervisor_virt_start; +--- sle11sp1-2010-03-29.orig/arch/x86/include/mach-xen/asm/irqflags.h 2009-11-06 10:52:22.000000000 +0100 ++++ sle11sp1-2010-03-29/arch/x86/include/mach-xen/asm/irqflags.h 2009-11-06 11:12:01.000000000 +0100 +@@ -12,7 +12,7 @@ + * includes these barriers, for example. + */ + +-#define xen_save_fl(void) (current_vcpu_info()->evtchn_upcall_mask) ++#define xen_save_fl(void) vcpu_info_read(evtchn_upcall_mask) + + #define xen_restore_fl(f) \ + do { \ +@@ -28,7 +28,7 @@ do { \ + + #define xen_irq_disable() \ + do { \ +- current_vcpu_info()->evtchn_upcall_mask = 1; \ ++ vcpu_info_write(evtchn_upcall_mask, 1); \ + barrier(); \ + } while (0) + +@@ -90,8 +90,6 @@ static inline void halt(void) + #define evtchn_upcall_pending /* 0 */ + #define evtchn_upcall_mask 1 + +-#define sizeof_vcpu_shift 6 +- + #ifdef CONFIG_X86_64 + # define __REG_si %rsi + # define __CPU_num PER_CPU_VAR(cpu_number) +@@ -100,6 +98,22 @@ static inline void halt(void) + # define __CPU_num TI_cpu(%ebp) + #endif + ++#ifdef CONFIG_XEN_VCPU_INFO_PLACEMENT ++ ++#define GET_VCPU_INFO PER_CPU(vcpu_info, __REG_si) ++#define __DISABLE_INTERRUPTS movb $1,PER_CPU_VAR(vcpu_info+evtchn_upcall_mask) ++#define __ENABLE_INTERRUPTS movb $0,PER_CPU_VAR(vcpu_info+evtchn_upcall_mask) ++#define __TEST_PENDING cmpb $0,PER_CPU_VAR(vcpu_info+evtchn_upcall_pending+0) ++#define DISABLE_INTERRUPTS(clb) __DISABLE_INTERRUPTS ++#define ENABLE_INTERRUPTS(clb) __ENABLE_INTERRUPTS ++ ++#define __SIZEOF_DISABLE_INTERRUPTS 8 ++#define __SIZEOF_TEST_PENDING 8 ++ ++#else /* CONFIG_XEN_VCPU_INFO_PLACEMENT */ ++ ++#define sizeof_vcpu_shift 6 ++ + #ifdef CONFIG_SMP + #define GET_VCPU_INFO movl __CPU_num,%esi ; \ + shl $sizeof_vcpu_shift,%esi ; \ +@@ -116,15 +130,21 @@ static inline void halt(void) + #define ENABLE_INTERRUPTS(clb) GET_VCPU_INFO ; \ + __ENABLE_INTERRUPTS + ++#define __SIZEOF_DISABLE_INTERRUPTS 4 ++#define __SIZEOF_TEST_PENDING 3 ++ ++#endif /* CONFIG_XEN_VCPU_INFO_PLACEMENT */ ++ + #ifndef CONFIG_X86_64 + #define INTERRUPT_RETURN iret +-#define ENABLE_INTERRUPTS_SYSEXIT __ENABLE_INTERRUPTS ; \ ++#define ENABLE_INTERRUPTS_SYSEXIT \ ++ movb $0,evtchn_upcall_mask(%esi) /* __ENABLE_INTERRUPTS */ ; \ + sysexit_scrit: /**** START OF SYSEXIT CRITICAL REGION ****/ ; \ +- __TEST_PENDING ; \ ++ cmpb $0,evtchn_upcall_pending(%esi) /* __TEST_PENDING */ ; \ + jnz 14f /* process more events if necessary... */ ; \ + movl PT_ESI(%esp), %esi ; \ + sysexit ; \ +-14: __DISABLE_INTERRUPTS ; \ ++14: movb $1,evtchn_upcall_mask(%esi) /* __DISABLE_INTERRUPTS */ ; \ + TRACE_IRQS_OFF ; \ + sysexit_ecrit: /**** END OF SYSEXIT CRITICAL REGION ****/ ; \ + mov $__KERNEL_PERCPU, %ecx ; \ +--- sle11sp1-2010-03-29.orig/arch/x86/include/mach-xen/asm/pgtable_64.h 2009-10-13 17:22:09.000000000 +0200 ++++ sle11sp1-2010-03-29/arch/x86/include/mach-xen/asm/pgtable_64.h 2009-11-06 11:12:01.000000000 +0100 +@@ -117,6 +117,8 @@ static inline void xen_set_pgd(pgd_t *pg + + #define __pte_mfn(_pte) (((_pte).pte & PTE_PFN_MASK) >> PAGE_SHIFT) + ++extern unsigned long early_arbitrary_virt_to_mfn(void *va); ++ + /* + * Conversion functions: convert a page and protection to a page entry, + * and a page entry and page directory to the page they refer to. +--- sle11sp1-2010-03-29.orig/arch/x86/include/mach-xen/asm/system.h 2009-11-06 10:52:22.000000000 +0100 ++++ sle11sp1-2010-03-29/arch/x86/include/mach-xen/asm/system.h 2009-11-06 11:12:01.000000000 +0100 +@@ -233,8 +233,8 @@ static inline void xen_write_cr0(unsigne + asm volatile("mov %0,%%cr0": : "r" (val), "m" (__force_order)); + } + +-#define xen_read_cr2() (current_vcpu_info()->arch.cr2) +-#define xen_write_cr2(val) ((void)(current_vcpu_info()->arch.cr2 = (val))) ++#define xen_read_cr2() vcpu_info_read(arch.cr2) ++#define xen_write_cr2(val) vcpu_info_write(arch.cr2, val) + + static inline unsigned long xen_read_cr3(void) + { +--- sle11sp1-2010-03-29.orig/arch/x86/kernel/cpu/common-xen.c 2010-01-18 17:05:30.000000000 +0100 ++++ sle11sp1-2010-03-29/arch/x86/kernel/cpu/common-xen.c 2009-11-06 11:12:01.000000000 +0100 +@@ -335,8 +335,16 @@ static const char *__cpuinit table_looku + __u32 cpu_caps_cleared[NCAPINTS] __cpuinitdata; + __u32 cpu_caps_set[NCAPINTS] __cpuinitdata; + +-void load_percpu_segment(int cpu) ++void __ref load_percpu_segment(int cpu) + { ++#ifdef CONFIG_XEN_VCPU_INFO_PLACEMENT ++ static bool done; ++ ++ if (!done) { ++ done = true; ++ adjust_boot_vcpu_info(); ++ } ++#endif + #ifdef CONFIG_X86_32 + loadsegment(fs, __KERNEL_PERCPU); + #else +--- sle11sp1-2010-03-29.orig/arch/x86/kernel/entry_32-xen.S 2009-10-13 17:01:47.000000000 +0200 ++++ sle11sp1-2010-03-29/arch/x86/kernel/entry_32-xen.S 2009-11-06 11:12:01.000000000 +0100 +@@ -463,6 +463,9 @@ sysenter_exit: + movl PT_EIP(%esp), %edx + movl PT_OLDESP(%esp), %ecx + xorl %ebp,%ebp ++#ifdef CONFIG_XEN_VCPU_INFO_PLACEMENT ++ GET_VCPU_INFO ++#endif + TRACE_IRQS_ON + 1: mov PT_FS(%esp), %fs + PTGS_TO_GS +@@ -975,7 +978,9 @@ critical_region_fixup: + + .section .rodata,"a" + critical_fixup_table: +- .byte -1,-1,-1 # testb $0xff,(%esi) = __TEST_PENDING ++ .rept __SIZEOF_TEST_PENDING ++ .byte -1 ++ .endr + .byte -1,-1 # jnz 14f + .byte 0 # pop %ebx + .byte 1 # pop %ecx +@@ -994,7 +999,9 @@ critical_fixup_table: + .byte 10,10,10 # add $8,%esp + #endif + .byte 12 # iret +- .byte -1,-1,-1,-1 # movb $1,1(%esi) = __DISABLE_INTERRUPTS ++ .rept __SIZEOF_DISABLE_INTERRUPTS ++ .byte -1 ++ .endr + .previous + + # Hypervisor uses this for application faults while it executes. +--- sle11sp1-2010-03-29.orig/arch/x86/kernel/head-xen.c 2009-10-15 15:32:46.000000000 +0200 ++++ sle11sp1-2010-03-29/arch/x86/kernel/head-xen.c 2009-11-06 11:12:01.000000000 +0100 +@@ -151,6 +151,8 @@ void __init xen_start_kernel(void) + HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO); + memset(empty_zero_page, 0, sizeof(empty_zero_page)); + ++ setup_vcpu_info(0); ++ + /* Set up mapping of lowest 1MB of physical memory. */ + for (i = 0; i < NR_FIX_ISAMAPS; i++) + if (is_initial_xendomain()) +--- sle11sp1-2010-03-29.orig/arch/x86/kernel/time-xen.c 2010-02-04 09:43:52.000000000 +0100 ++++ sle11sp1-2010-03-29/arch/x86/kernel/time-xen.c 2010-02-09 17:20:06.000000000 +0100 +@@ -276,16 +276,10 @@ static void get_time_values_from_xen(uns + local_irq_restore(flags); + } + +-static inline int time_values_up_to_date(unsigned int cpu) ++static inline int time_values_up_to_date(void) + { +- struct vcpu_time_info *src; +- struct shadow_time_info *dst; +- +- src = &vcpu_info(cpu)->time; +- dst = &per_cpu(shadow_time, cpu); +- + rmb(); +- return (dst->version == src->version); ++ return percpu_read(shadow_time.version) == vcpu_info_read(time.version); + } + + static void sync_xen_wallclock(unsigned long dummy); +@@ -331,7 +325,7 @@ static unsigned long long local_clock(vo + local_time_version = shadow->version; + rdtsc_barrier(); + time = shadow->system_timestamp + get_nsec_offset(shadow); +- if (!time_values_up_to_date(cpu)) ++ if (!time_values_up_to_date()) + get_time_values_from_xen(cpu); + barrier(); + } while (local_time_version != shadow->version); +@@ -455,7 +449,7 @@ static irqreturn_t timer_interrupt(int i + delta_cpu -= per_cpu(processed_system_time, cpu); + + get_runstate_snapshot(&runstate); +- } while (!time_values_up_to_date(cpu)); ++ } while (!time_values_up_to_date()); + + if ((unlikely(delta < -(s64)permitted_clock_jitter) || + unlikely(delta_cpu < -(s64)permitted_clock_jitter)) +--- sle11sp1-2010-03-29.orig/arch/x86/mm/hypervisor.c 2009-12-11 15:27:37.000000000 +0100 ++++ sle11sp1-2010-03-29/arch/x86/mm/hypervisor.c 2010-01-05 16:47:18.000000000 +0100 +@@ -41,6 +41,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -50,7 +51,105 @@ + EXPORT_SYMBOL(hypercall_page); + + shared_info_t *__read_mostly HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page; ++#ifndef CONFIG_XEN_VCPU_INFO_PLACEMENT + EXPORT_SYMBOL(HYPERVISOR_shared_info); ++#else ++DEFINE_PER_CPU(struct vcpu_info, vcpu_info) __aligned(sizeof(struct vcpu_info)); ++EXPORT_PER_CPU_SYMBOL(vcpu_info); ++ ++void __ref setup_vcpu_info(unsigned int cpu) ++{ ++ struct vcpu_info *v = &per_cpu(vcpu_info, cpu); ++ struct vcpu_register_vcpu_info info; ++#ifdef CONFIG_X86_64 ++ static bool first = true; ++ ++ if (first) { ++ first = false; ++ info.mfn = early_arbitrary_virt_to_mfn(v); ++ } else ++#endif ++ info.mfn = arbitrary_virt_to_mfn(v); ++ info.offset = offset_in_page(v); ++ ++ if (HYPERVISOR_vcpu_op(VCPUOP_register_vcpu_info, ++ cpu, &info)) ++ BUG(); ++} ++ ++void __init adjust_boot_vcpu_info(void) ++{ ++ unsigned long lpfn, rpfn, lmfn, rmfn; ++ pte_t *lpte, *rpte; ++ unsigned int level; ++ mmu_update_t mmu[2]; ++ ++ /* ++ * setup_vcpu_info() cannot be used more than once for a given (v)CPU, ++ * hence we must swap the underlying MFNs of the two pages holding old ++ * and new vcpu_info of the boot CPU. ++ * ++ * Do *not* use __get_cpu_var() or percpu_{write,...}() here, as the per- ++ * CPU segment didn't get reloaded yet. Using percpu_read(), as in ++ * arch_use_lazy_mmu_mode(), though undesirable, is safe except for the ++ * accesses to variables that were updated in setup_percpu_areas(). ++ */ ++ lpte = lookup_address((unsigned long)&per_cpu_var(vcpu_info) ++ + (__per_cpu_load - __per_cpu_start), ++ &level); ++ rpte = lookup_address((unsigned long)&per_cpu(vcpu_info, 0), &level); ++ BUG_ON(!lpte || !(pte_flags(*lpte) & _PAGE_PRESENT)); ++ BUG_ON(!rpte || !(pte_flags(*rpte) & _PAGE_PRESENT)); ++ lmfn = __pte_mfn(*lpte); ++ rmfn = __pte_mfn(*rpte); ++ ++ if (lmfn == rmfn) ++ return; ++ ++ lpfn = mfn_to_local_pfn(lmfn); ++ rpfn = mfn_to_local_pfn(rmfn); ++ ++ printk(KERN_INFO ++ "Swapping MFNs for PFN %lx and %lx (MFN %lx and %lx)\n", ++ lpfn, rpfn, lmfn, rmfn); ++ ++ xen_l1_entry_update(lpte, pfn_pte_ma(rmfn, pte_pgprot(*lpte))); ++ xen_l1_entry_update(rpte, pfn_pte_ma(lmfn, pte_pgprot(*rpte))); ++#ifdef CONFIG_X86_64 ++ if (HYPERVISOR_update_va_mapping((unsigned long)__va(lpfn<> PAGE_SHIFT; ++} ++ + #ifndef CONFIG_XEN + static int __init parse_direct_gbpages_off(char *arg) + { +--- sle11sp1-2010-03-29.orig/drivers/xen/Kconfig 2010-03-29 09:13:58.000000000 +0200 ++++ sle11sp1-2010-03-29/drivers/xen/Kconfig 2010-03-29 09:14:20.000000000 +0200 +@@ -366,6 +366,18 @@ config XEN_COMPAT + default 0x030002 if XEN_COMPAT_030002_AND_LATER + default 0 + ++config XEN_VCPU_INFO_PLACEMENT ++ bool "Place shared vCPU info in per-CPU storage" ++# depends on X86 && (XEN_COMPAT >= 0x00030101) ++ depends on X86 ++ depends on !XEN_COMPAT_030002_AND_LATER ++ depends on !XEN_COMPAT_030004_AND_LATER ++ depends on !XEN_COMPAT_030100_AND_LATER ++ default SMP ++ ---help--- ++ This allows faster access to the per-vCPU shared info ++ structure. ++ + endmenu + + config HAVE_IRQ_IGNORE_UNHANDLED +--- sle11sp1-2010-03-29.orig/drivers/xen/core/evtchn.c 2010-02-09 17:19:07.000000000 +0100 ++++ sle11sp1-2010-03-29/drivers/xen/core/evtchn.c 2010-02-09 17:20:42.000000000 +0100 +@@ -316,6 +316,24 @@ static DEFINE_PER_CPU(unsigned int, upca + static DEFINE_PER_CPU(unsigned int, current_l1i); + static DEFINE_PER_CPU(unsigned int, current_l2i); + ++#ifndef vcpu_info_xchg ++#define vcpu_info_xchg(fld, val) xchg(¤t_vcpu_info()->fld, val) ++#endif ++ ++#ifndef percpu_xadd ++#define percpu_xadd(var, val) \ ++({ \ ++ typeof(per_cpu_var(var)) __tmp_var__; \ ++ unsigned long flags; \ ++ local_irq_save(flags); \ ++ __tmp_var__ = get_cpu_var(var); \ ++ __get_cpu_var(var) += (val); \ ++ put_cpu_var(var); \ ++ local_irq_restore(flags); \ ++ __tmp_var__; \ ++}) ++#endif ++ + /* NB. Interrupts are disabled on entry. */ + asmlinkage void __irq_entry evtchn_do_upcall(struct pt_regs *regs) + { +@@ -324,25 +342,25 @@ asmlinkage void __irq_entry evtchn_do_up + unsigned long masked_l1, masked_l2; + unsigned int l1i, l2i, start_l1i, start_l2i, port, count, i; + int irq; +- vcpu_info_t *vcpu_info = current_vcpu_info(); + + exit_idle(); + irq_enter(); + + do { + /* Avoid a callback storm when we reenable delivery. */ +- vcpu_info->evtchn_upcall_pending = 0; ++ vcpu_info_write(evtchn_upcall_pending, 0); + + /* Nested invocations bail immediately. */ +- percpu_add(upcall_count, 1); +- if (unlikely(percpu_read(upcall_count) != 1)) ++ if (unlikely(percpu_xadd(upcall_count, 1))) + break; + + #ifndef CONFIG_X86 /* No need for a barrier -- XCHG is a barrier on x86. */ + /* Clear master flag /before/ clearing selector flag. */ + wmb(); ++#else ++ barrier(); + #endif +- l1 = xchg(&vcpu_info->evtchn_pending_sel, 0); ++ l1 = vcpu_info_xchg(evtchn_pending_sel, 0); + + start_l1i = l1i = percpu_read(current_l1i); + start_l2i = percpu_read(current_l2i); +@@ -1369,7 +1387,6 @@ void unmask_evtchn(int port) + { + shared_info_t *s = HYPERVISOR_shared_info; + unsigned int cpu = smp_processor_id(); +- vcpu_info_t *vcpu_info = &s->vcpu_info[cpu]; + + BUG_ON(!irqs_disabled()); + +@@ -1383,10 +1400,13 @@ void unmask_evtchn(int port) + synch_clear_bit(port, s->evtchn_mask); + + /* Did we miss an interrupt 'edge'? Re-fire if so. */ +- if (synch_test_bit(port, s->evtchn_pending) && +- !synch_test_and_set_bit(port / BITS_PER_LONG, +- &vcpu_info->evtchn_pending_sel)) +- vcpu_info->evtchn_upcall_pending = 1; ++ if (synch_test_bit(port, s->evtchn_pending)) { ++ vcpu_info_t *vcpu_info = current_vcpu_info(); ++ ++ if (!synch_test_and_set_bit(port / BITS_PER_LONG, ++ &vcpu_info->evtchn_pending_sel)) ++ vcpu_info->evtchn_upcall_pending = 1; ++ } + } + EXPORT_SYMBOL_GPL(unmask_evtchn); + +--- sle11sp1-2010-03-29.orig/drivers/xen/core/machine_reboot.c 2009-12-18 14:15:04.000000000 +0100 ++++ sle11sp1-2010-03-29/drivers/xen/core/machine_reboot.c 2009-12-18 14:15:17.000000000 +0100 +@@ -73,7 +73,7 @@ static void pre_suspend(void) + mfn_to_pfn(xen_start_info->console.domU.mfn); + } + +-static void post_suspend(int suspend_cancelled) ++static void post_suspend(int suspend_cancelled, int fast_suspend) + { + int i, j, k, fpp; + unsigned long shinfo_mfn; +@@ -90,8 +90,21 @@ static void post_suspend(int suspend_can + #ifdef CONFIG_SMP + cpumask_copy(vcpu_initialized_mask, cpu_online_mask); + #endif +- for_each_possible_cpu(i) ++ for_each_possible_cpu(i) { + setup_runstate_area(i); ++ ++#ifdef CONFIG_XEN_VCPU_INFO_PLACEMENT ++ if (fast_suspend && i != smp_processor_id() ++ && HYPERVISOR_vcpu_op(VCPUOP_down, i, NULL)) ++ BUG(); ++ ++ setup_vcpu_info(i); ++ ++ if (fast_suspend && i != smp_processor_id() ++ && HYPERVISOR_vcpu_op(VCPUOP_up, i, NULL)) ++ BUG(); ++#endif ++ } + } + + shinfo_mfn = xen_start_info->shared_info >> PAGE_SHIFT; +@@ -133,7 +146,7 @@ static void post_suspend(int suspend_can + #define switch_idle_mm() ((void)0) + #define mm_pin_all() ((void)0) + #define pre_suspend() xen_pre_suspend() +-#define post_suspend(x) xen_post_suspend(x) ++#define post_suspend(x, f) xen_post_suspend(x) + + #endif + +@@ -164,7 +177,7 @@ static int take_machine_down(void *_susp + BUG_ON(suspend_cancelled > 0); + suspend->resume_notifier(suspend_cancelled); + if (suspend_cancelled >= 0) { +- post_suspend(suspend_cancelled); ++ post_suspend(suspend_cancelled, suspend->fast_suspend); + sysdev_resume(); + } + if (!suspend_cancelled) { +--- sle11sp1-2010-03-29.orig/drivers/xen/core/smpboot.c 2010-03-22 12:59:04.000000000 +0100 ++++ sle11sp1-2010-03-29/drivers/xen/core/smpboot.c 2010-03-22 12:59:52.000000000 +0100 +@@ -369,8 +369,13 @@ void __init smp_prepare_cpus(unsigned in + + void __init smp_prepare_boot_cpu(void) + { ++ unsigned int cpu; ++ + switch_to_new_gdt(smp_processor_id()); + prefill_possible_map(); ++ for_each_possible_cpu(cpu) ++ if (cpu != smp_processor_id()) ++ setup_vcpu_info(cpu); + } + + #ifdef CONFIG_HOTPLUG_CPU +--- sle11sp1-2010-03-29.orig/drivers/xen/core/spinlock.c 2010-03-22 12:58:39.000000000 +0100 ++++ sle11sp1-2010-03-29/drivers/xen/core/spinlock.c 2010-03-22 12:59:54.000000000 +0100 +@@ -104,7 +104,7 @@ bool xen_spin_wait(raw_spinlock_t *lock, + spinning.prev = percpu_read(spinning); + smp_wmb(); + percpu_write(spinning, &spinning); +- upcall_mask = current_vcpu_info()->evtchn_upcall_mask; ++ upcall_mask = vcpu_info_read(evtchn_upcall_mask); + + do { + bool nested = false; +@@ -170,12 +170,12 @@ bool xen_spin_wait(raw_spinlock_t *lock, + * intended event processing will happen with the poll + * call. + */ +- current_vcpu_info()->evtchn_upcall_mask = +- nested ? upcall_mask : flags; ++ vcpu_info_write(evtchn_upcall_mask, ++ nested ? upcall_mask : flags); + + xen_poll_irq(irq); + +- current_vcpu_info()->evtchn_upcall_mask = upcall_mask; ++ vcpu_info_write(evtchn_upcall_mask, upcall_mask); + + rc = !xen_test_irq_pending(irq); + if (!rc) diff --git a/xen-x86-pmd-handling b/xen-x86-pmd-handling new file mode 100644 index 0000000..3a2731d --- /dev/null +++ b/xen-x86-pmd-handling @@ -0,0 +1,605 @@ +From: jbeulich@novell.com +Subject: consolidate pmd/pud/pgd entry handling +Patch-mainline: obsolete + +--- sle11sp1-2010-03-22.orig/arch/x86/include/mach-xen/asm/hypervisor.h 2009-11-23 10:45:08.000000000 +0100 ++++ sle11sp1-2010-03-22/arch/x86/include/mach-xen/asm/hypervisor.h 2009-11-23 10:49:39.000000000 +0100 +@@ -99,10 +99,12 @@ void xen_invlpg(unsigned long ptr); + void xen_l1_entry_update(pte_t *ptr, pte_t val); + void xen_l2_entry_update(pmd_t *ptr, pmd_t val); + void xen_l3_entry_update(pud_t *ptr, pud_t val); /* x86_64/PAE */ +-void xen_l4_entry_update(pgd_t *ptr, pgd_t val); /* x86_64 only */ ++void xen_l4_entry_update(pgd_t *ptr, int user, pgd_t val); /* x86_64 only */ + void xen_pgd_pin(unsigned long ptr); + void xen_pgd_unpin(unsigned long ptr); + ++void xen_init_pgd_pin(void); ++ + void xen_set_ldt(const void *ptr, unsigned int ents); + + #ifdef CONFIG_SMP +@@ -335,6 +337,18 @@ MULTI_update_va_mapping( + } + + static inline void ++MULTI_mmu_update(multicall_entry_t *mcl, mmu_update_t *req, ++ unsigned int count, unsigned int *success_count, ++ domid_t domid) ++{ ++ mcl->op = __HYPERVISOR_mmu_update; ++ mcl->args[0] = (unsigned long)req; ++ mcl->args[1] = count; ++ mcl->args[2] = (unsigned long)success_count; ++ mcl->args[3] = domid; ++} ++ ++static inline void + MULTI_grant_table_op(multicall_entry_t *mcl, unsigned int cmd, + void *uop, unsigned int count) + { +--- sle11sp1-2010-03-22.orig/arch/x86/include/mach-xen/asm/pgalloc.h 2010-03-22 12:47:01.000000000 +0100 ++++ sle11sp1-2010-03-22/arch/x86/include/mach-xen/asm/pgalloc.h 2010-03-22 12:59:30.000000000 +0100 +@@ -75,20 +75,16 @@ static inline void pmd_populate(struct m + struct page *pte) + { + unsigned long pfn = page_to_pfn(pte); ++ pmd_t ent = __pmd(((pmdval_t)pfn << PAGE_SHIFT) | _PAGE_TABLE); + + paravirt_alloc_pte(mm, pfn); +- if (PagePinned(virt_to_page(mm->pgd))) { +- if (!PageHighMem(pte)) +- BUG_ON(HYPERVISOR_update_va_mapping( +- (unsigned long)__va(pfn << PAGE_SHIFT), +- pfn_pte(pfn, PAGE_KERNEL_RO), 0)); +-#ifndef CONFIG_X86_64 +- else if (!TestSetPagePinned(pte)) +- kmap_flush_unused(); ++ if (PagePinned(virt_to_page(pmd))) { ++#ifndef CONFIG_HIGHPTE ++ BUG_ON(PageHighMem(pte)); + #endif +- set_pmd(pmd, __pmd(((pmdval_t)pfn << PAGE_SHIFT) | _PAGE_TABLE)); ++ set_pmd(pmd, ent); + } else +- *pmd = __pmd(((pmdval_t)pfn << PAGE_SHIFT) | _PAGE_TABLE); ++ *pmd = ent; + } + + #define pmd_pgtable(pmd) pmd_page(pmd) +@@ -116,39 +112,28 @@ extern void pud_populate(struct mm_struc + #else /* !CONFIG_X86_PAE */ + static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd) + { ++ pud_t ent = __pud(_PAGE_TABLE | __pa(pmd)); ++ + paravirt_alloc_pmd(mm, __pa(pmd) >> PAGE_SHIFT); +- if (unlikely(PagePinned(virt_to_page((mm)->pgd)))) { +- BUG_ON(HYPERVISOR_update_va_mapping( +- (unsigned long)pmd, +- pfn_pte(virt_to_phys(pmd)>>PAGE_SHIFT, +- PAGE_KERNEL_RO), 0)); +- set_pud(pud, __pud(_PAGE_TABLE | __pa(pmd))); +- } else +- *pud = __pud(_PAGE_TABLE | __pa(pmd)); ++ if (PagePinned(virt_to_page(pud))) ++ set_pud(pud, ent); ++ else ++ *pud = ent; + } + #endif /* CONFIG_X86_PAE */ + + #if PAGETABLE_LEVELS > 3 + #define __user_pgd(pgd) ((pgd) + PTRS_PER_PGD) + +-/* +- * We need to use the batch mode here, but pgd_pupulate() won't be +- * be called frequently. +- */ + static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud) + { ++ pgd_t ent = __pgd(_PAGE_TABLE | __pa(pud)); ++ + paravirt_alloc_pud(mm, __pa(pud) >> PAGE_SHIFT); +- if (unlikely(PagePinned(virt_to_page((mm)->pgd)))) { +- BUG_ON(HYPERVISOR_update_va_mapping( +- (unsigned long)pud, +- pfn_pte(virt_to_phys(pud)>>PAGE_SHIFT, +- PAGE_KERNEL_RO), 0)); +- set_pgd(pgd, __pgd(_PAGE_TABLE | __pa(pud))); +- set_pgd(__user_pgd(pgd), __pgd(_PAGE_TABLE | __pa(pud))); +- } else { +- *(pgd) = __pgd(_PAGE_TABLE | __pa(pud)); +- *__user_pgd(pgd) = *(pgd); +- } ++ if (unlikely(PagePinned(virt_to_page(pgd)))) ++ xen_l4_entry_update(pgd, 1, ent); ++ else ++ *__user_pgd(pgd) = *pgd = ent; + } + + static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr) +--- sle11sp1-2010-03-22.orig/arch/x86/include/mach-xen/asm/pgtable-3level.h 2009-11-06 10:52:02.000000000 +0100 ++++ sle11sp1-2010-03-22/arch/x86/include/mach-xen/asm/pgtable-3level.h 2009-10-13 17:22:09.000000000 +0200 +@@ -61,12 +61,15 @@ static inline void __xen_pte_clear(pte_t + ptep->pte_high = 0; + } + +-static inline void xen_pmd_clear(pmd_t *pmd) +-{ +- xen_l2_entry_update(pmd, __pmd(0)); +-} ++#define xen_pmd_clear(pmd) \ ++({ \ ++ pmd_t *__pmdp = (pmd); \ ++ PagePinned(virt_to_page(__pmdp)) \ ++ ? set_pmd(__pmdp, __pmd(0)) \ ++ : (void)(*__pmdp = __pmd(0)); \ ++}) + +-static inline void pud_clear(pud_t *pudp) ++static inline void __xen_pud_clear(pud_t *pudp) + { + pgdval_t pgd; + +@@ -87,6 +90,14 @@ static inline void pud_clear(pud_t *pudp + xen_tlb_flush(); + } + ++#define xen_pud_clear(pudp) \ ++({ \ ++ pud_t *__pudp = (pudp); \ ++ PagePinned(virt_to_page(__pudp)) \ ++ ? __xen_pud_clear(__pudp) \ ++ : (void)(*__pudp = __pud(0)); \ ++}) ++ + #ifdef CONFIG_SMP + static inline pte_t xen_ptep_get_and_clear(pte_t *ptep, pte_t res) + { +--- sle11sp1-2010-03-22.orig/arch/x86/include/mach-xen/asm/pgtable_64.h 2009-11-06 10:52:09.000000000 +0100 ++++ sle11sp1-2010-03-22/arch/x86/include/mach-xen/asm/pgtable_64.h 2009-10-13 17:22:09.000000000 +0200 +@@ -79,33 +79,41 @@ static inline void xen_set_pmd(pmd_t *pm + xen_l2_entry_update(pmdp, pmd); + } + +-static inline void xen_pmd_clear(pmd_t *pmd) +-{ +- xen_set_pmd(pmd, xen_make_pmd(0)); +-} ++#define xen_pmd_clear(pmd) \ ++({ \ ++ pmd_t *__pmdp = (pmd); \ ++ PagePinned(virt_to_page(__pmdp)) \ ++ ? set_pmd(__pmdp, xen_make_pmd(0)) \ ++ : (void)(*__pmdp = xen_make_pmd(0)); \ ++}) + + static inline void xen_set_pud(pud_t *pudp, pud_t pud) + { + xen_l3_entry_update(pudp, pud); + } + +-static inline void xen_pud_clear(pud_t *pud) +-{ +- xen_set_pud(pud, xen_make_pud(0)); +-} ++#define xen_pud_clear(pud) \ ++({ \ ++ pud_t *__pudp = (pud); \ ++ PagePinned(virt_to_page(__pudp)) \ ++ ? set_pud(__pudp, xen_make_pud(0)) \ ++ : (void)(*__pudp = xen_make_pud(0)); \ ++}) + + #define __user_pgd(pgd) ((pgd) + PTRS_PER_PGD) + + static inline void xen_set_pgd(pgd_t *pgdp, pgd_t pgd) + { +- xen_l4_entry_update(pgdp, pgd); ++ xen_l4_entry_update(pgdp, 0, pgd); + } + +-static inline void xen_pgd_clear(pgd_t *pgd) +-{ +- xen_set_pgd(pgd, xen_make_pgd(0)); +- xen_set_pgd(__user_pgd(pgd), xen_make_pgd(0)); +-} ++#define xen_pgd_clear(pgd) \ ++({ \ ++ pgd_t *__pgdp = (pgd); \ ++ PagePinned(virt_to_page(__pgdp)) \ ++ ? xen_l4_entry_update(__pgdp, 1, xen_make_pgd(0)) \ ++ : (void)(*__user_pgd(__pgdp) = *__pgdp = xen_make_pgd(0)); \ ++}) + + #define __pte_mfn(_pte) (((_pte).pte & PTE_PFN_MASK) >> PAGE_SHIFT) + +--- sle11sp1-2010-03-22.orig/arch/x86/mm/hypervisor.c 2009-06-09 15:52:17.000000000 +0200 ++++ sle11sp1-2010-03-22/arch/x86/mm/hypervisor.c 2009-12-11 15:27:37.000000000 +0100 +@@ -360,31 +360,91 @@ void xen_l1_entry_update(pte_t *ptr, pte + } + EXPORT_SYMBOL_GPL(xen_l1_entry_update); + ++static void do_lN_entry_update(mmu_update_t *mmu, unsigned int mmu_count, ++ struct page *page) ++{ ++ if (likely(page)) { ++ multicall_entry_t mcl[2]; ++ unsigned long pfn = page_to_pfn(page); ++ ++ MULTI_update_va_mapping(mcl, ++ (unsigned long)__va(pfn << PAGE_SHIFT), ++ pfn_pte(pfn, PAGE_KERNEL_RO), 0); ++ SetPagePinned(page); ++ MULTI_mmu_update(mcl + 1, mmu, mmu_count, NULL, DOMID_SELF); ++ if (unlikely(HYPERVISOR_multicall_check(mcl, 2, NULL))) ++ BUG(); ++ } else if (unlikely(HYPERVISOR_mmu_update(mmu, mmu_count, ++ NULL, DOMID_SELF) < 0)) ++ BUG(); ++} ++ + void xen_l2_entry_update(pmd_t *ptr, pmd_t val) + { + mmu_update_t u; ++ struct page *page = NULL; ++ ++ if (likely(pmd_present(val)) && likely(!pmd_large(val)) ++ && likely(mem_map) ++ && likely(PagePinned(virt_to_page(ptr)))) { ++ page = pmd_page(val); ++ if (unlikely(PagePinned(page))) ++ page = NULL; ++ else if (PageHighMem(page)) { ++#ifndef CONFIG_HIGHPTE ++ BUG(); ++#endif ++ kmap_flush_unused(); ++ page = NULL; ++ } ++ } + u.ptr = virt_to_machine(ptr); + u.val = __pmd_val(val); +- BUG_ON(HYPERVISOR_mmu_update(&u, 1, NULL, DOMID_SELF) < 0); ++ do_lN_entry_update(&u, 1, page); + } + + #if defined(CONFIG_X86_PAE) || defined(CONFIG_X86_64) + void xen_l3_entry_update(pud_t *ptr, pud_t val) + { + mmu_update_t u; ++ struct page *page = NULL; ++ ++ if (likely(pud_present(val)) ++#ifdef CONFIG_X86_64 ++ && likely(!pud_large(val)) ++#endif ++ && likely(mem_map) ++ && likely(PagePinned(virt_to_page(ptr)))) { ++ page = pud_page(val); ++ if (unlikely(PagePinned(page))) ++ page = NULL; ++ } + u.ptr = virt_to_machine(ptr); + u.val = __pud_val(val); +- BUG_ON(HYPERVISOR_mmu_update(&u, 1, NULL, DOMID_SELF) < 0); ++ do_lN_entry_update(&u, 1, page); + } + #endif + + #ifdef CONFIG_X86_64 +-void xen_l4_entry_update(pgd_t *ptr, pgd_t val) ++void xen_l4_entry_update(pgd_t *ptr, int user, pgd_t val) + { +- mmu_update_t u; +- u.ptr = virt_to_machine(ptr); +- u.val = __pgd_val(val); +- BUG_ON(HYPERVISOR_mmu_update(&u, 1, NULL, DOMID_SELF) < 0); ++ mmu_update_t u[2]; ++ struct page *page = NULL; ++ ++ if (likely(pgd_present(val)) && likely(mem_map) ++ && likely(PagePinned(virt_to_page(ptr)))) { ++ page = pgd_page(val); ++ if (unlikely(PagePinned(page))) ++ page = NULL; ++ } ++ u[0].ptr = virt_to_machine(ptr); ++ u[0].val = __pgd_val(val); ++ if (user) { ++ u[1].ptr = virt_to_machine(__user_pgd(ptr)); ++ u[1].val = __pgd_val(val); ++ do_lN_entry_update(u, 2, page); ++ } else ++ do_lN_entry_update(u, 1, page); + } + #endif /* CONFIG_X86_64 */ + +--- sle11sp1-2010-03-22.orig/arch/x86/mm/init_32-xen.c 2010-03-11 09:32:10.000000000 +0100 ++++ sle11sp1-2010-03-22/arch/x86/mm/init_32-xen.c 2009-10-13 17:22:09.000000000 +0200 +@@ -748,6 +748,8 @@ static void __init zone_sizes_init(void) + #endif + + free_area_init_nodes(max_zone_pfns); ++ ++ xen_init_pgd_pin(); + } + + static unsigned long __init setup_node_bootmem(int nodeid, +@@ -1018,8 +1020,6 @@ void __init mem_init(void) + + save_pg_dir(); + zap_low_mappings(true); +- +- SetPagePinned(virt_to_page(init_mm.pgd)); + } + + #ifdef CONFIG_MEMORY_HOTPLUG +--- sle11sp1-2010-03-22.orig/arch/x86/mm/init_64-xen.c 2010-03-11 09:32:17.000000000 +0100 ++++ sle11sp1-2010-03-22/arch/x86/mm/init_64-xen.c 2009-11-12 17:37:05.000000000 +0100 +@@ -192,8 +192,11 @@ static pud_t *fill_pud(pgd_t *pgd, unsig + { + if (pgd_none(*pgd)) { + pud_t *pud = (pud_t *)spp_getpage(); +- make_page_readonly(pud, XENFEAT_writable_page_tables); +- pgd_populate(&init_mm, pgd, pud); ++ if (!after_bootmem) { ++ make_page_readonly(pud, XENFEAT_writable_page_tables); ++ xen_l4_entry_update(pgd, __pgd(__pa(pud) | _PAGE_TABLE)); ++ } else ++ pgd_populate(&init_mm, pgd, pud); + if (pud != pud_offset(pgd, 0)) + printk(KERN_ERR "PAGETABLE BUG #00! %p <-> %p\n", + pud, pud_offset(pgd, 0)); +@@ -205,8 +208,11 @@ static pmd_t *fill_pmd(pud_t *pud, unsig + { + if (pud_none(*pud)) { + pmd_t *pmd = (pmd_t *) spp_getpage(); +- make_page_readonly(pmd, XENFEAT_writable_page_tables); +- pud_populate(&init_mm, pud, pmd); ++ if (!after_bootmem) { ++ make_page_readonly(pmd, XENFEAT_writable_page_tables); ++ xen_l3_entry_update(pud, __pud(__pa(pmd) | _PAGE_TABLE)); ++ } else ++ pud_populate(&init_mm, pud, pmd); + if (pmd != pmd_offset(pud, 0)) + printk(KERN_ERR "PAGETABLE BUG #01! %p <-> %p\n", + pmd, pmd_offset(pud, 0)); +@@ -535,7 +541,6 @@ phys_pmd_init(pmd_t *pmd_page, unsigned + XENFEAT_writable_page_tables); + *pmd = __pmd(pte_phys | _PAGE_TABLE); + } else { +- make_page_readonly(pte, XENFEAT_writable_page_tables); + spin_lock(&init_mm.page_table_lock); + pmd_populate_kernel(&init_mm, pmd, __va(pte_phys)); + spin_unlock(&init_mm.page_table_lock); +@@ -624,7 +629,6 @@ phys_pud_init(pud_t *pud_page, unsigned + else + *pud = __pud(pmd_phys | _PAGE_TABLE); + } else { +- make_page_readonly(pmd, XENFEAT_writable_page_tables); + spin_lock(&init_mm.page_table_lock); + pud_populate(&init_mm, pud, __va(pmd_phys)); + spin_unlock(&init_mm.page_table_lock); +@@ -798,7 +802,6 @@ kernel_physical_mapping_init(unsigned lo + XENFEAT_writable_page_tables); + xen_l4_entry_update(pgd, __pgd(pud_phys | _PAGE_TABLE)); + } else { +- make_page_readonly(pud, XENFEAT_writable_page_tables); + spin_lock(&init_mm.page_table_lock); + pgd_populate(&init_mm, pgd, __va(pud_phys)); + spin_unlock(&init_mm.page_table_lock); +@@ -854,7 +857,7 @@ void __init paging_init(void) + + free_area_init_nodes(max_zone_pfns); + +- SetPagePinned(virt_to_page(init_mm.pgd)); ++ xen_init_pgd_pin(); + } + + /* +--- sle11sp1-2010-03-22.orig/arch/x86/mm/pgtable-xen.c 2010-03-22 12:50:44.000000000 +0100 ++++ sle11sp1-2010-03-22/arch/x86/mm/pgtable-xen.c 2010-03-22 12:59:39.000000000 +0100 +@@ -65,16 +65,16 @@ early_param("userpte", setup_userpte); + void __pte_free(pgtable_t pte) + { + if (!PageHighMem(pte)) { +- unsigned long va = (unsigned long)page_address(pte); +- unsigned int level; +- pte_t *ptep = lookup_address(va, &level); +- +- BUG_ON(!ptep || level != PG_LEVEL_4K || !pte_present(*ptep)); +- if (!pte_write(*ptep) +- && HYPERVISOR_update_va_mapping(va, +- mk_pte(pte, PAGE_KERNEL), +- 0)) +- BUG(); ++ if (PagePinned(pte)) { ++ unsigned long pfn = page_to_pfn(pte); ++ ++ if (HYPERVISOR_update_va_mapping((unsigned long)__va(pfn << PAGE_SHIFT), ++ pfn_pte(pfn, ++ PAGE_KERNEL), ++ 0)) ++ BUG(); ++ ClearPagePinned(pte); ++ } + } else + #ifdef CONFIG_HIGHPTE + ClearPagePinned(pte); +@@ -116,14 +116,15 @@ pmd_t *pmd_alloc_one(struct mm_struct *m + + void __pmd_free(pgtable_t pmd) + { +- unsigned long va = (unsigned long)page_address(pmd); +- unsigned int level; +- pte_t *ptep = lookup_address(va, &level); +- +- BUG_ON(!ptep || level != PG_LEVEL_4K || !pte_present(*ptep)); +- if (!pte_write(*ptep) +- && HYPERVISOR_update_va_mapping(va, mk_pte(pmd, PAGE_KERNEL), 0)) +- BUG(); ++ if (PagePinned(pmd)) { ++ unsigned long pfn = page_to_pfn(pmd); ++ ++ if (HYPERVISOR_update_va_mapping((unsigned long)__va(pfn << PAGE_SHIFT), ++ pfn_pte(pfn, PAGE_KERNEL), ++ 0)) ++ BUG(); ++ ClearPagePinned(pmd); ++ } + + ClearPageForeign(pmd); + init_page_count(pmd); +@@ -211,21 +212,20 @@ static inline unsigned int pgd_walk_set_ + { + unsigned long pfn = page_to_pfn(page); + +- if (PageHighMem(page)) { +- if (pgprot_val(flags) & _PAGE_RW) +- ClearPagePinned(page); +- else +- SetPagePinned(page); +- } else { +- MULTI_update_va_mapping(per_cpu(pb_mcl, cpu) + seq, +- (unsigned long)__va(pfn << PAGE_SHIFT), +- pfn_pte(pfn, flags), 0); +- if (unlikely(++seq == PIN_BATCH)) { +- if (unlikely(HYPERVISOR_multicall_check(per_cpu(pb_mcl, cpu), +- PIN_BATCH, NULL))) +- BUG(); +- seq = 0; +- } ++ if (pgprot_val(flags) & _PAGE_RW) ++ ClearPagePinned(page); ++ else ++ SetPagePinned(page); ++ if (PageHighMem(page)) ++ return seq; ++ MULTI_update_va_mapping(per_cpu(pb_mcl, cpu) + seq, ++ (unsigned long)__va(pfn << PAGE_SHIFT), ++ pfn_pte(pfn, flags), 0); ++ if (unlikely(++seq == PIN_BATCH)) { ++ if (unlikely(HYPERVISOR_multicall_check(per_cpu(pb_mcl, cpu), ++ PIN_BATCH, NULL))) ++ BUG(); ++ seq = 0; + } + + return seq; +@@ -272,6 +272,16 @@ static void pgd_walk(pgd_t *pgd_base, pg + } + } + ++#ifdef CONFIG_X86_PAE ++ for (; g < PTRS_PER_PGD; g++, pgd++) { ++ BUG_ON(pgd_none(*pgd)); ++ pud = pud_offset(pgd, 0); ++ BUG_ON(pud_none(*pud)); ++ pmd = pmd_offset(pud, 0); ++ seq = pgd_walk_set_prot(virt_to_page(pmd),flags,cpu,seq); ++ } ++#endif ++ + mcl = per_cpu(pb_mcl, cpu); + #ifdef CONFIG_X86_64 + if (unlikely(seq > PIN_BATCH - 2)) { +@@ -307,6 +317,51 @@ static void pgd_walk(pgd_t *pgd_base, pg + put_cpu(); + } + ++void __init xen_init_pgd_pin(void) ++{ ++ pgd_t *pgd = init_mm.pgd; ++ pud_t *pud; ++ pmd_t *pmd; ++ unsigned int g, u, m; ++ ++ if (xen_feature(XENFEAT_auto_translated_physmap)) ++ return; ++ ++ SetPagePinned(virt_to_page(pgd)); ++ for (g = 0; g < PTRS_PER_PGD; g++, pgd++) { ++#ifndef CONFIG_X86_PAE ++ if (g >= pgd_index(HYPERVISOR_VIRT_START) ++ && g <= pgd_index(HYPERVISOR_VIRT_END - 1)) ++ continue; ++#endif ++ if (!pgd_present(*pgd)) ++ continue; ++ pud = pud_offset(pgd, 0); ++ if (PTRS_PER_PUD > 1) /* not folded */ ++ SetPagePinned(virt_to_page(pud)); ++ for (u = 0; u < PTRS_PER_PUD; u++, pud++) { ++ if (!pud_present(*pud)) ++ continue; ++ pmd = pmd_offset(pud, 0); ++ if (PTRS_PER_PMD > 1) /* not folded */ ++ SetPagePinned(virt_to_page(pmd)); ++ for (m = 0; m < PTRS_PER_PMD; m++, pmd++) { ++#ifdef CONFIG_X86_PAE ++ if (g == pgd_index(HYPERVISOR_VIRT_START) ++ && m >= pmd_index(HYPERVISOR_VIRT_START)) ++ continue; ++#endif ++ if (!pmd_present(*pmd)) ++ continue; ++ SetPagePinned(pmd_page(*pmd)); ++ } ++ } ++ } ++#ifdef CONFIG_X86_64 ++ SetPagePinned(virt_to_page(level3_user_pgt)); ++#endif ++} ++ + static void __pgd_pin(pgd_t *pgd) + { + pgd_walk(pgd, PAGE_KERNEL_RO); +@@ -497,21 +552,18 @@ static void pgd_dtor(pgd_t *pgd) + + void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmd) + { +- struct page *page = virt_to_page(pmd); +- unsigned long pfn = page_to_pfn(page); +- +- paravirt_alloc_pmd(mm, __pa(pmd) >> PAGE_SHIFT); +- + /* Note: almost everything apart from _PAGE_PRESENT is + reserved at the pmd (PDPT) level. */ +- if (PagePinned(virt_to_page(mm->pgd))) { +- BUG_ON(PageHighMem(page)); +- BUG_ON(HYPERVISOR_update_va_mapping( +- (unsigned long)__va(pfn << PAGE_SHIFT), +- pfn_pte(pfn, PAGE_KERNEL_RO), 0)); +- set_pud(pudp, __pud(__pa(pmd) | _PAGE_PRESENT)); +- } else +- *pudp = __pud(__pa(pmd) | _PAGE_PRESENT); ++ pud_t pud = __pud(__pa(pmd) | _PAGE_PRESENT); ++ ++ paravirt_alloc_pmd(mm, page_to_pfn(virt_to_page(pmd))); ++ ++ if (likely(!PagePinned(virt_to_page(pudp)))) { ++ *pudp = pud; ++ return; ++ } ++ ++ set_pud(pudp, pud); + + /* + * According to Intel App note "TLBs, Paging-Structure Caches, +@@ -606,13 +658,10 @@ static void pgd_prepopulate_pmd(struct m + i++, pud++, addr += PUD_SIZE) { + pmd_t *pmd = pmds[i]; + +- if (i >= KERNEL_PGD_BOUNDARY) { ++ if (i >= KERNEL_PGD_BOUNDARY) + memcpy(pmd, + (pmd_t *)pgd_page_vaddr(swapper_pg_dir[i]), + sizeof(pmd_t) * PTRS_PER_PMD); +- make_lowmem_page_readonly( +- pmd, XENFEAT_writable_page_tables); +- } + + /* It is safe to poke machine addresses of pmds under the pgd_lock. */ + pud_populate(mm, pud, pmd); diff --git a/xen-x86-time-per-cpu b/xen-x86-time-per-cpu new file mode 100644 index 0000000..17b3983 --- /dev/null +++ b/xen-x86-time-per-cpu @@ -0,0 +1,186 @@ +From: jbeulich@novell.com +Subject: fold per-CPU accounting data into a structure +Patch-mainline: n/a + +... to simplify generated code, especially in timer_interrupt(). This +becomes more important with more such data elements added (i.e. by +patches.xen/xen-x86-xtime-lock). + +--- sle11sp1-2010-02-17.orig/arch/x86/kernel/time-xen.c 2010-02-18 17:30:48.000000000 +0100 ++++ sle11sp1-2010-02-17/arch/x86/kernel/time-xen.c 2010-02-18 17:32:00.000000000 +0100 +@@ -57,12 +57,15 @@ static u32 shadow_tv_version; + + /* Keep track of last time we did processing/updating of jiffies and xtime. */ + static u64 processed_system_time; /* System time (ns) at last processing. */ +-static DEFINE_PER_CPU(u64, processed_system_time); +-static DEFINE_PER_CPU(u64, accounted_system_time); + +-/* How much CPU time was spent blocked and how much was 'stolen'? */ +-static DEFINE_PER_CPU(u64, processed_stolen_time); +-static DEFINE_PER_CPU(u64, processed_blocked_time); ++struct local_time_info { ++ u64 processed_system; ++ u64 accounted_system; ++ /* How much CPU time was spent blocked and how much was 'stolen'? */ ++ u64 accounted_stolen; ++ u64 accounted_blocked; ++}; ++static DEFINE_PER_CPU(struct local_time_info, local_time); + + /* Current runstate of each CPU (updated automatically by the hypervisor). */ + DEFINE_PER_CPU(struct vcpu_runstate_info, runstate); +@@ -440,6 +443,7 @@ static irqreturn_t timer_interrupt(int i + s64 delta, delta_cpu, stolen, blocked; + unsigned int i, cpu = smp_processor_id(); + struct shadow_time_info *shadow = &per_cpu(shadow_time, cpu); ++ struct local_time_info *local = &per_cpu(local_time, cpu); + bool duty = false; + struct vcpu_runstate_info runstate; + +@@ -468,7 +472,7 @@ static irqreturn_t timer_interrupt(int i + delta = delta_cpu = + shadow->system_timestamp + get_nsec_offset(shadow); + delta -= processed_system_time; +- delta_cpu -= per_cpu(processed_system_time, cpu); ++ delta_cpu -= local->processed_system; + + get_runstate_snapshot(&runstate); + } while (!time_values_up_to_date()); +@@ -482,10 +486,10 @@ static irqreturn_t timer_interrupt(int i + "processed=%Lx/%Lx\n", + cpu, delta, delta_cpu, shadow->system_timestamp, + get_nsec_offset(shadow), blocked, +- per_cpu(processed_system_time, cpu)); ++ local->processed_system); + for_each_cpu_and(i, cpu_online_mask, cpumask_of(cpu)) + printk(" %u: %Lx\n", i, +- per_cpu(processed_system_time, i)); ++ per_cpu(local_time.processed_system, i)); + } + } else if (unlikely(delta_cpu < -(s64)permitted_clock_jitter)) { + blocked = processed_system_time; +@@ -496,10 +500,10 @@ static irqreturn_t timer_interrupt(int i + " shadow=%Lx off=%Lx processed=%Lx/%Lx\n", + cpu, delta_cpu, shadow->system_timestamp, + get_nsec_offset(shadow), blocked, +- per_cpu(processed_system_time, cpu)); ++ local->processed_system); + for_each_cpu_and(i, cpu_online_mask, cpumask_of(cpu)) + printk(" %u: %Lx\n", i, +- per_cpu(processed_system_time, i)); ++ per_cpu(local_time.processed_system, i)); + } + } else if (duty) { + /* System-wide jiffy work. */ +@@ -524,11 +528,10 @@ static irqreturn_t timer_interrupt(int i + } + + delta = delta_cpu; +- delta_cpu += per_cpu(processed_system_time, cpu) +- - per_cpu(accounted_system_time, cpu); ++ delta_cpu += local->processed_system - local->accounted_system; + if (delta >= NS_PER_TICK) { + do_div(delta, NS_PER_TICK); +- per_cpu(processed_system_time, cpu) += delta * NS_PER_TICK; ++ local->processed_system += delta * NS_PER_TICK; + } + + /* +@@ -537,14 +540,14 @@ static irqreturn_t timer_interrupt(int i + */ + stolen = runstate.time[RUNSTATE_runnable] + + runstate.time[RUNSTATE_offline] +- - per_cpu(processed_stolen_time, cpu); ++ - local->accounted_stolen; + if ((stolen > 0) && (delta_cpu > 0)) { + delta_cpu -= stolen; + if (unlikely(delta_cpu < 0)) + stolen += delta_cpu; /* clamp local-time progress */ + do_div(stolen, NS_PER_TICK); +- per_cpu(processed_stolen_time, cpu) += stolen * NS_PER_TICK; +- per_cpu(accounted_system_time, cpu) += stolen * NS_PER_TICK; ++ local->accounted_stolen += stolen * NS_PER_TICK; ++ local->accounted_system += stolen * NS_PER_TICK; + account_steal_ticks(stolen); + } + +@@ -553,21 +556,21 @@ static irqreturn_t timer_interrupt(int i + * ensures that the ticks are accounted as idle/wait. + */ + blocked = runstate.time[RUNSTATE_blocked] +- - per_cpu(processed_blocked_time, cpu); ++ - local->accounted_blocked; + if ((blocked > 0) && (delta_cpu > 0)) { + delta_cpu -= blocked; + if (unlikely(delta_cpu < 0)) + blocked += delta_cpu; /* clamp local-time progress */ + do_div(blocked, NS_PER_TICK); +- per_cpu(processed_blocked_time, cpu) += blocked * NS_PER_TICK; +- per_cpu(accounted_system_time, cpu) += blocked * NS_PER_TICK; ++ local->accounted_blocked += blocked * NS_PER_TICK; ++ local->accounted_system += blocked * NS_PER_TICK; + account_idle_ticks(blocked); + } + + /* Account user/system ticks. */ + if (delta_cpu > 0) { + do_div(delta_cpu, NS_PER_TICK); +- per_cpu(accounted_system_time, cpu) += delta_cpu * NS_PER_TICK; ++ local->accounted_system += delta_cpu * NS_PER_TICK; + if (user_mode_vm(get_irq_regs())) + account_user_time(current, (cputime_t)delta_cpu, + (cputime_t)delta_cpu); +@@ -606,9 +609,9 @@ static void init_missing_ticks_accountin + { + struct vcpu_runstate_info *runstate = setup_runstate_area(cpu); + +- per_cpu(processed_blocked_time, cpu) = ++ per_cpu(local_time.accounted_blocked, cpu) = + runstate->time[RUNSTATE_blocked]; +- per_cpu(processed_stolen_time, cpu) = ++ per_cpu(local_time.accounted_stolen, cpu) = + runstate->time[RUNSTATE_runnable] + + runstate->time[RUNSTATE_offline]; + } +@@ -668,8 +671,8 @@ static void xen_clocksource_resume(void) + BUG(); + } + get_time_values_from_xen(cpu); +- per_cpu(accounted_system_time, cpu) = +- per_cpu(processed_system_time, cpu) = ++ per_cpu(local_time.accounted_system, cpu) = ++ per_cpu(local_time.processed_system, cpu) = + per_cpu(shadow_time, 0).system_timestamp; + init_missing_ticks_accounting(cpu); + } +@@ -770,8 +773,8 @@ void __init time_init(void) + get_time_values_from_xen(0); + + processed_system_time = per_cpu(shadow_time, 0).system_timestamp; +- per_cpu(processed_system_time, 0) = processed_system_time; +- per_cpu(accounted_system_time, 0) = processed_system_time; ++ per_cpu(local_time.processed_system, 0) = processed_system_time; ++ per_cpu(local_time.accounted_system, 0) = processed_system_time; + init_missing_ticks_accounting(0); + + clocksource_register(&clocksource_xen); +@@ -849,7 +852,7 @@ static void stop_hz_timer(void) + singleshot.timeout_abs_ns = jiffies_to_st(j); + if (!singleshot.timeout_abs_ns) + return; +- local = per_cpu(processed_system_time, cpu); ++ local = per_cpu(local_time.processed_system, cpu); + if ((s64)(singleshot.timeout_abs_ns - local) <= NS_PER_TICK) { + cpumask_clear_cpu(cpu, nohz_cpu_mask); + singleshot.timeout_abs_ns = local + NS_PER_TICK; +@@ -918,8 +921,8 @@ int __cpuinit local_setup_timer(unsigned + do { + seq = read_seqbegin(&xtime_lock); + /* Use cpu0 timestamp: cpu's shadow is not initialised yet. */ +- per_cpu(accounted_system_time, cpu) = +- per_cpu(processed_system_time, cpu) = ++ per_cpu(local_time.accounted_system, cpu) = ++ per_cpu(local_time.processed_system, cpu) = + per_cpu(shadow_time, 0).system_timestamp; + init_missing_ticks_accounting(cpu); + } while (read_seqretry(&xtime_lock, seq)); diff --git a/xen-x86-xtime-lock b/xen-x86-xtime-lock new file mode 100644 index 0000000..fa60f59 --- /dev/null +++ b/xen-x86-xtime-lock @@ -0,0 +1,245 @@ +From: jbeulich@novell.com +Subject: reduce contention on xtime_lock +Patch-mainline: n/a +References: bnc#569014, bnc#571041, bnc#571769, bnc#572146 + +Especially on large systems the number of CPUs queueing up on +xtime_lock may become signficiant, and (as reported in the bugs above) +may even prevent proper operation of the system when Xen is using +deep C-states. There is, however, no need for all CPUs in the system +to update global time - it is sufficient to have a single (at any given +point in time) CPU being responsible for this. + +Also, while touching that code, avoid calling printk() with xtime_lock +held. + +--- sle11sp1-2010-02-17.orig/arch/x86/kernel/time-xen.c 2010-02-18 17:30:18.000000000 +0100 ++++ sle11sp1-2010-02-17/arch/x86/kernel/time-xen.c 2010-02-18 17:33:07.000000000 +0100 +@@ -58,6 +58,7 @@ static u32 shadow_tv_version; + /* Keep track of last time we did processing/updating of jiffies and xtime. */ + static u64 processed_system_time; /* System time (ns) at last processing. */ + static DEFINE_PER_CPU(u64, processed_system_time); ++static DEFINE_PER_CPU(u64, accounted_system_time); + + /* How much CPU time was spent blocked and how much was 'stolen'? */ + static DEFINE_PER_CPU(u64, processed_stolen_time); +@@ -123,6 +124,19 @@ static int __init __permitted_clock_jitt + __setup("permitted_clock_jitter=", __permitted_clock_jitter); + + /* ++ * Limit on the number of CPUs that may concurrently attempt to acquire ++ * xtime_lock in timer_interrupt() (reducing contention potentially leading ++ * to a live lock on systems with many CPUs. ++ */ ++static unsigned int __read_mostly duty_limit = -2; ++static int __init set_duty_limit(char *str) ++{ ++ duty_limit = simple_strtoul(str, NULL, 0) - 1; ++ return 1; ++} ++__setup("timer_duty_limit=", set_duty_limit); ++ ++/* + * Scale a 64-bit delta by scaling and multiplying by a 32-bit fraction, + * yielding a 64-bit result. + */ +@@ -422,9 +436,11 @@ EXPORT_SYMBOL(profile_pc); + */ + static irqreturn_t timer_interrupt(int irq, void *dev_id) + { ++ static unsigned int contention_count; + s64 delta, delta_cpu, stolen, blocked; + unsigned int i, cpu = smp_processor_id(); + struct shadow_time_info *shadow = &per_cpu(shadow_time, cpu); ++ bool duty = false; + struct vcpu_runstate_info runstate; + + /* Keep nmi watchdog up to date */ +@@ -437,7 +453,13 @@ static irqreturn_t timer_interrupt(int i + * the irq version of write_lock because as just said we have irq + * locally disabled. -arca + */ +- write_seqlock(&xtime_lock); ++ asm (LOCK_PREFIX "xaddl %1, %0" ++ : "+m" (contention_count), "=r" (i) : "1" (1)); ++ if (i <= duty_limit) { ++ write_seqlock(&xtime_lock); ++ duty = true; ++ } ++ asm (LOCK_PREFIX "decl %0" : "+m" (contention_count)); + + do { + get_time_values_from_xen(cpu); +@@ -451,40 +473,63 @@ static irqreturn_t timer_interrupt(int i + get_runstate_snapshot(&runstate); + } while (!time_values_up_to_date()); + +- if ((unlikely(delta < -(s64)permitted_clock_jitter) || +- unlikely(delta_cpu < -(s64)permitted_clock_jitter)) +- && printk_ratelimit()) { +- printk("Timer ISR/%u: Time went backwards: " +- "delta=%lld delta_cpu=%lld shadow=%lld " +- "off=%lld processed=%lld cpu_processed=%lld\n", +- cpu, delta, delta_cpu, shadow->system_timestamp, +- (s64)get_nsec_offset(shadow), +- processed_system_time, +- per_cpu(processed_system_time, cpu)); +- for (i = 0; i < num_online_cpus(); i++) +- printk(" %d: %lld\n", i, +- per_cpu(processed_system_time, i)); +- } ++ if (duty && unlikely(delta < -(s64)permitted_clock_jitter)) { ++ blocked = processed_system_time; ++ write_sequnlock(&xtime_lock); ++ if (printk_ratelimit()) { ++ printk("Timer ISR/%u: Time went backwards: " ++ "delta=%Ld/%Ld shadow=%Lx off=%Lx " ++ "processed=%Lx/%Lx\n", ++ cpu, delta, delta_cpu, shadow->system_timestamp, ++ get_nsec_offset(shadow), blocked, ++ per_cpu(processed_system_time, cpu)); ++ for_each_cpu_and(i, cpu_online_mask, cpumask_of(cpu)) ++ printk(" %u: %Lx\n", i, ++ per_cpu(processed_system_time, i)); ++ } ++ } else if (unlikely(delta_cpu < -(s64)permitted_clock_jitter)) { ++ blocked = processed_system_time; ++ if (duty) ++ write_sequnlock(&xtime_lock); ++ if (printk_ratelimit()) { ++ printk("Timer ISR/%u: Time went backwards: delta=%Ld" ++ " shadow=%Lx off=%Lx processed=%Lx/%Lx\n", ++ cpu, delta_cpu, shadow->system_timestamp, ++ get_nsec_offset(shadow), blocked, ++ per_cpu(processed_system_time, cpu)); ++ for_each_cpu_and(i, cpu_online_mask, cpumask_of(cpu)) ++ printk(" %u: %Lx\n", i, ++ per_cpu(processed_system_time, i)); ++ } ++ } else if (duty) { ++ /* System-wide jiffy work. */ ++ if (delta >= NS_PER_TICK) { ++ do_div(delta, NS_PER_TICK); ++ processed_system_time += delta * NS_PER_TICK; ++ while (delta > HZ) { ++ clobber_induction_variable(delta); ++ do_timer(HZ); ++ delta -= HZ; ++ } ++ do_timer(delta); ++ } + +- /* System-wide jiffy work. */ +- if (delta >= NS_PER_TICK) { +- do_div(delta, NS_PER_TICK); +- processed_system_time += delta * NS_PER_TICK; +- while (delta > HZ) { +- clobber_induction_variable(delta); +- do_timer(HZ); +- delta -= HZ; ++ if (shadow_tv_version != HYPERVISOR_shared_info->wc_version) { ++ update_wallclock(); ++ if (keventd_up()) ++ schedule_work(&clock_was_set_work); + } +- do_timer(delta); +- } + +- if (shadow_tv_version != HYPERVISOR_shared_info->wc_version) { +- update_wallclock(); +- if (keventd_up()) +- schedule_work(&clock_was_set_work); ++ write_sequnlock(&xtime_lock); + } + +- write_sequnlock(&xtime_lock); ++ delta = delta_cpu; ++ delta_cpu += per_cpu(processed_system_time, cpu) ++ - per_cpu(accounted_system_time, cpu); ++ if (delta >= NS_PER_TICK) { ++ do_div(delta, NS_PER_TICK); ++ per_cpu(processed_system_time, cpu) += delta * NS_PER_TICK; ++ } + + /* + * Account stolen ticks. +@@ -499,7 +544,7 @@ static irqreturn_t timer_interrupt(int i + stolen += delta_cpu; /* clamp local-time progress */ + do_div(stolen, NS_PER_TICK); + per_cpu(processed_stolen_time, cpu) += stolen * NS_PER_TICK; +- per_cpu(processed_system_time, cpu) += stolen * NS_PER_TICK; ++ per_cpu(accounted_system_time, cpu) += stolen * NS_PER_TICK; + account_steal_ticks(stolen); + } + +@@ -515,14 +560,14 @@ static irqreturn_t timer_interrupt(int i + blocked += delta_cpu; /* clamp local-time progress */ + do_div(blocked, NS_PER_TICK); + per_cpu(processed_blocked_time, cpu) += blocked * NS_PER_TICK; +- per_cpu(processed_system_time, cpu) += blocked * NS_PER_TICK; ++ per_cpu(accounted_system_time, cpu) += blocked * NS_PER_TICK; + account_idle_ticks(blocked); + } + + /* Account user/system ticks. */ + if (delta_cpu > 0) { + do_div(delta_cpu, NS_PER_TICK); +- per_cpu(processed_system_time, cpu) += delta_cpu * NS_PER_TICK; ++ per_cpu(accounted_system_time, cpu) += delta_cpu * NS_PER_TICK; + if (user_mode_vm(get_irq_regs())) + account_user_time(current, (cputime_t)delta_cpu, + (cputime_t)delta_cpu); +@@ -623,6 +668,7 @@ static void xen_clocksource_resume(void) + BUG(); + } + get_time_values_from_xen(cpu); ++ per_cpu(accounted_system_time, cpu) = + per_cpu(processed_system_time, cpu) = + per_cpu(shadow_time, 0).system_timestamp; + init_missing_ticks_accounting(cpu); +@@ -725,6 +771,7 @@ void __init time_init(void) + + processed_system_time = per_cpu(shadow_time, 0).system_timestamp; + per_cpu(processed_system_time, 0) = processed_system_time; ++ per_cpu(accounted_system_time, 0) = processed_system_time; + init_missing_ticks_accounting(0); + + clocksource_register(&clocksource_xen); +@@ -735,6 +782,9 @@ void __init time_init(void) + + /* Cannot request_irq() until kmem is initialised. */ + late_time_init = setup_cpu0_timer_irq; ++ ++ if (!(duty_limit + 2)) ++ duty_limit = __fls(nr_cpu_ids); + } + + /* Convert jiffies to system time. */ +@@ -773,6 +823,7 @@ static void stop_hz_timer(void) + struct vcpu_set_singleshot_timer singleshot; + unsigned int cpu = smp_processor_id(); + unsigned long j; ++ u64 local; + int rc; + + cpumask_set_cpu(cpu, nohz_cpu_mask); +@@ -798,6 +849,11 @@ static void stop_hz_timer(void) + singleshot.timeout_abs_ns = jiffies_to_st(j); + if (!singleshot.timeout_abs_ns) + return; ++ local = per_cpu(processed_system_time, cpu); ++ if ((s64)(singleshot.timeout_abs_ns - local) <= NS_PER_TICK) { ++ cpumask_clear_cpu(cpu, nohz_cpu_mask); ++ singleshot.timeout_abs_ns = local + NS_PER_TICK; ++ } + singleshot.timeout_abs_ns += NS_PER_TICK / 2; + singleshot.flags = 0; + rc = HYPERVISOR_vcpu_op(VCPUOP_set_singleshot_timer, cpu, &singleshot); +@@ -862,6 +918,7 @@ int __cpuinit local_setup_timer(unsigned + do { + seq = read_seqbegin(&xtime_lock); + /* Use cpu0 timestamp: cpu's shadow is not initialised yet. */ ++ per_cpu(accounted_system_time, cpu) = + per_cpu(processed_system_time, cpu) = + per_cpu(shadow_time, 0).system_timestamp; + init_missing_ticks_accounting(cpu); diff --git a/xen-x86_64-dump-user-pgt b/xen-x86_64-dump-user-pgt new file mode 100644 index 0000000..cfc9bb0 --- /dev/null +++ b/xen-x86_64-dump-user-pgt @@ -0,0 +1,51 @@ +From: jbeulich@novell.com +Subject: dump the correct page tables for user mode faults +Patch-mainline: obsolete + +--- head-2009-10-12.orig/arch/x86/mm/fault-xen.c 2009-10-13 13:40:11.000000000 +0200 ++++ head-2009-10-12/arch/x86/mm/fault-xen.c 2009-10-13 17:28:26.000000000 +0200 +@@ -328,6 +328,7 @@ static void dump_pagetable(unsigned long + out: + printk(KERN_CONT "\n"); + } ++#define dump_pagetable(addr, krnl) dump_pagetable(addr) + + #else /* CONFIG_X86_64: */ + +@@ -452,7 +453,7 @@ static int bad_address(void *p) + return probe_kernel_address((unsigned long *)p, dummy); + } + +-static void dump_pagetable(unsigned long address) ++static void dump_pagetable(unsigned long address, bool kernel) + { + pgd_t *base = __va(read_cr3() & PHYSICAL_PAGE_MASK); + pgd_t *pgd = base + pgd_index(address); +@@ -460,6 +461,9 @@ static void dump_pagetable(unsigned long + pmd_t *pmd; + pte_t *pte; + ++ if (!kernel) ++ pgd = __user_pgd(base) + pgd_index(address); ++ + if (bad_address(pgd)) + goto bad; + +@@ -598,7 +602,7 @@ show_fault_oops(struct pt_regs *regs, un + printk(KERN_ALERT "IP:"); + printk_address(regs->ip, 1); + +- dump_pagetable(address); ++ dump_pagetable(address, !(error_code & PF_USER)); + } + + static noinline void +@@ -615,7 +619,7 @@ pgtable_bad(struct pt_regs *regs, unsign + + printk(KERN_ALERT "%s: Corrupted page table at address %lx\n", + tsk->comm, address); +- dump_pagetable(address); ++ dump_pagetable(address, !(error_code & PF_USER)); + + tsk->thread.cr2 = address; + tsk->thread.trap_no = 14; diff --git a/xen-x86_64-note-init-p2m b/xen-x86_64-note-init-p2m new file mode 100644 index 0000000..63fe63c --- /dev/null +++ b/xen-x86_64-note-init-p2m @@ -0,0 +1,343 @@ +From: jbeulich@novell.com +Subject: eliminate scalability issues from initial mapping setup +Patch-mainline: obsolete +References: bnc#417417 + +Direct Xen to place the initial P->M table outside of the initial +mapping, as otherwise the 1G (implementation) / 2G (theoretical) +restriction on the size of the initial mapping limits the amount +of memory a domain can be handed initially. + +Note that the flags passed to HYPERVISOR_update_va_mapping() from +__make_page_writable() and make_lowmem_page_writable() are +intentionally not including UVMF_ALL. This is intended to be on optimal +choice between the overhead of a potential spurious page fault (as +remote CPUs may still have read-only translations in their TLBs) and +the overhead of cross processor flushes. Flushing on the local CPU +shouldn't be as expensive (and hence can be viewed as an optimization +avoiding the spurious page fault on the local CPU), but is required +when the functions are used before the page fault handler gets set up. + +--- sle11sp1-2010-03-22.orig/arch/x86/kernel/head64-xen.c 2009-11-06 10:52:22.000000000 +0100 ++++ sle11sp1-2010-03-22/arch/x86/kernel/head64-xen.c 2009-12-04 12:12:10.000000000 +0100 +@@ -123,6 +123,14 @@ void __init x86_64_start_reservations(ch + + reserve_early(__pa_symbol(&_text), __pa_symbol(&__bss_stop), "TEXT DATA BSS"); + ++ if (xen_feature(XENFEAT_auto_translated_physmap)) ++ xen_start_info->mfn_list = ~0UL; ++ else if (xen_start_info->mfn_list < __START_KERNEL_map) ++ reserve_early(xen_start_info->first_p2m_pfn << PAGE_SHIFT, ++ (xen_start_info->first_p2m_pfn ++ + xen_start_info->nr_p2m_frames) << PAGE_SHIFT, ++ "INITP2M"); ++ + /* + * At this point everything still needed from the boot loader + * or BIOS or kernel text should be early reserved or marked not +--- sle11sp1-2010-03-22.orig/arch/x86/kernel/head_64-xen.S 2009-12-04 14:37:53.000000000 +0100 ++++ sle11sp1-2010-03-22/arch/x86/kernel/head_64-xen.S 2009-12-04 14:38:07.000000000 +0100 +@@ -17,6 +17,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -146,6 +147,7 @@ ENTRY(empty_zero_page) + ELFNOTE(Xen, XEN_ELFNOTE_ENTRY, .quad startup_64) + ELFNOTE(Xen, XEN_ELFNOTE_HYPERCALL_PAGE, .quad hypercall_page) + ELFNOTE(Xen, XEN_ELFNOTE_L1_MFN_VALID, .quad _PAGE_PRESENT, _PAGE_PRESENT) ++ ELFNOTE(Xen, XEN_ELFNOTE_INIT_P2M, .quad VMEMMAP_START) + ELFNOTE(Xen, XEN_ELFNOTE_FEATURES, .asciz "writable_page_tables|writable_descriptor_tables|auto_translated_physmap|pae_pgdir_above_4gb|supervisor_mode_kernel") + ELFNOTE(Xen, XEN_ELFNOTE_LOADER, .asciz "generic") + ELFNOTE(Xen, XEN_ELFNOTE_SUSPEND_CANCEL, .long 1) +--- sle11sp1-2010-03-22.orig/arch/x86/kernel/setup-xen.c 2010-02-09 17:19:48.000000000 +0100 ++++ sle11sp1-2010-03-22/arch/x86/kernel/setup-xen.c 2010-02-10 16:12:19.000000000 +0100 +@@ -1138,7 +1138,7 @@ void __init setup_arch(char **cmdline_p) + difference = xen_start_info->nr_pages - max_pfn; + + set_xen_guest_handle(reservation.extent_start, +- ((unsigned long *)xen_start_info->mfn_list) + max_pfn); ++ phys_to_machine_mapping + max_pfn); + reservation.nr_extents = difference; + ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation, + &reservation); +@@ -1155,14 +1155,86 @@ void __init setup_arch(char **cmdline_p) + phys_to_machine_mapping = alloc_bootmem_pages( + max_pfn * sizeof(unsigned long)); + memcpy(phys_to_machine_mapping, +- (unsigned long *)xen_start_info->mfn_list, ++ __va(__pa(xen_start_info->mfn_list)), + p2m_pages * sizeof(unsigned long)); + memset(phys_to_machine_mapping + p2m_pages, ~0, + (max_pfn - p2m_pages) * sizeof(unsigned long)); +- free_bootmem( +- __pa(xen_start_info->mfn_list), +- PFN_PHYS(PFN_UP(xen_start_info->nr_pages * +- sizeof(unsigned long)))); ++ ++#ifdef CONFIG_X86_64 ++ if (xen_start_info->mfn_list == VMEMMAP_START) { ++ /* ++ * Since it is well isolated we can (and since it is ++ * perhaps large we should) also free the page tables ++ * mapping the initial P->M table. ++ */ ++ unsigned long va = VMEMMAP_START, pa; ++ pgd_t *pgd = pgd_offset_k(va); ++ pud_t *pud_page = pud_offset(pgd, 0); ++ ++ BUILD_BUG_ON(VMEMMAP_START & ~PGDIR_MASK); ++ xen_l4_entry_update(pgd, __pgd(0)); ++ for(;;) { ++ pud_t *pud = pud_page + pud_index(va); ++ ++ if (pud_none(*pud)) ++ va += PUD_SIZE; ++ else if (pud_large(*pud)) { ++ pa = pud_val(*pud) & PHYSICAL_PAGE_MASK; ++ make_pages_writable(__va(pa), ++ PUD_SIZE >> PAGE_SHIFT, ++ XENFEAT_writable_page_tables); ++ free_bootmem(pa, PUD_SIZE); ++ va += PUD_SIZE; ++ } else { ++ pmd_t *pmd = pmd_offset(pud, va); ++ ++ if (pmd_large(*pmd)) { ++ pa = pmd_val(*pmd) & PHYSICAL_PAGE_MASK; ++ make_pages_writable(__va(pa), ++ PMD_SIZE >> PAGE_SHIFT, ++ XENFEAT_writable_page_tables); ++ free_bootmem(pa, PMD_SIZE); ++ } else if (!pmd_none(*pmd)) { ++ pte_t *pte = pte_offset_kernel(pmd, va); ++ ++ for (i = 0; i < PTRS_PER_PTE; ++i) { ++ if (pte_none(pte[i])) ++ break; ++ pa = pte_pfn(pte[i]) << PAGE_SHIFT; ++ make_page_writable(__va(pa), ++ XENFEAT_writable_page_tables); ++ free_bootmem(pa, PAGE_SIZE); ++ } ++ ClearPagePinned(virt_to_page(pte)); ++ make_page_writable(pte, ++ XENFEAT_writable_page_tables); ++ free_bootmem(__pa(pte), PAGE_SIZE); ++ } ++ va += PMD_SIZE; ++ if (pmd_index(va)) ++ continue; ++ ClearPagePinned(virt_to_page(pmd)); ++ make_page_writable(pmd, ++ XENFEAT_writable_page_tables); ++ free_bootmem(__pa((unsigned long)pmd ++ & PAGE_MASK), ++ PAGE_SIZE); ++ } ++ if (!pud_index(va)) ++ break; ++ } ++ ClearPagePinned(virt_to_page(pud_page)); ++ make_page_writable(pud_page, ++ XENFEAT_writable_page_tables); ++ free_bootmem(__pa((unsigned long)pud_page & PAGE_MASK), ++ PAGE_SIZE); ++ } else if (!WARN_ON(xen_start_info->mfn_list ++ < __START_KERNEL_map)) ++#endif ++ free_bootmem(__pa(xen_start_info->mfn_list), ++ PFN_PHYS(PFN_UP(xen_start_info->nr_pages * ++ sizeof(unsigned long)))); ++ + + /* + * Initialise the list of the frames that specify the list of +--- sle11sp1-2010-03-22.orig/arch/x86/mm/init-xen.c 2009-11-06 10:52:23.000000000 +0100 ++++ sle11sp1-2010-03-22/arch/x86/mm/init-xen.c 2009-12-04 12:12:10.000000000 +0100 +@@ -347,9 +347,22 @@ unsigned long __init_refok init_memory_m + + __flush_tlb_all(); + +- if (!after_bootmem && e820_table_top > e820_table_start) ++ if (!after_bootmem && e820_table_top > e820_table_start) { ++#ifdef CONFIG_X86_64 ++ if (xen_start_info->mfn_list < __START_KERNEL_map ++ && e820_table_start <= xen_start_info->first_p2m_pfn ++ && e820_table_top > xen_start_info->first_p2m_pfn) { ++ reserve_early(e820_table_start << PAGE_SHIFT, ++ xen_start_info->first_p2m_pfn ++ << PAGE_SHIFT, ++ "PGTABLE"); ++ e820_table_start = xen_start_info->first_p2m_pfn ++ + xen_start_info->nr_p2m_frames; ++ } ++#endif + reserve_early(e820_table_start << PAGE_SHIFT, + e820_table_top << PAGE_SHIFT, "PGTABLE"); ++ } + + if (!after_bootmem) + early_memtest(start, end); +--- sle11sp1-2010-03-22.orig/arch/x86/mm/init_64-xen.c 2009-12-04 12:11:43.000000000 +0100 ++++ sle11sp1-2010-03-22/arch/x86/mm/init_64-xen.c 2009-12-04 12:12:10.000000000 +0100 +@@ -181,6 +181,17 @@ static int __init nonx32_setup(char *str + } + __setup("noexec32=", nonx32_setup); + ++static __init unsigned long get_table_end(void) ++{ ++ BUG_ON(!e820_table_end); ++ if (xen_start_info->mfn_list < __START_KERNEL_map ++ && e820_table_end == xen_start_info->first_p2m_pfn) { ++ e820_table_end += xen_start_info->nr_p2m_frames; ++ e820_table_top += xen_start_info->nr_p2m_frames; ++ } ++ return e820_table_end++; ++} ++ + /* + * NOTE: This function is marked __ref because it calls __init function + * (alloc_bootmem_pages). It's safe to do it ONLY when after_bootmem == 0. +@@ -192,8 +203,7 @@ static __ref void *spp_getpage(void) + if (after_bootmem) + ptr = (void *) get_zeroed_page(GFP_ATOMIC | __GFP_NOTRACK); + else if (e820_table_end < e820_table_top) { +- ptr = __va(e820_table_end << PAGE_SHIFT); +- e820_table_end++; ++ ptr = __va(get_table_end() << PAGE_SHIFT); + memset(ptr, 0, PAGE_SIZE); + } else + ptr = alloc_bootmem_pages(PAGE_SIZE); +@@ -388,8 +398,7 @@ static __ref void *alloc_low_page(unsign + return adr; + } + +- BUG_ON(!e820_table_end); +- pfn = e820_table_end++; ++ pfn = get_table_end(); + if (pfn >= e820_table_top) + panic("alloc_low_page: ran out of memory"); + +@@ -415,14 +424,29 @@ static inline int __meminit make_readonl + /* Make new page tables read-only on the first pass. */ + if (!xen_feature(XENFEAT_writable_page_tables) + && !max_pfn_mapped +- && (paddr >= (e820_table_start << PAGE_SHIFT)) +- && (paddr < (e820_table_top << PAGE_SHIFT))) +- readonly = 1; ++ && (paddr >= (e820_table_start << PAGE_SHIFT))) { ++ unsigned long top = e820_table_top; ++ ++ /* Account for the range get_table_end() skips. */ ++ if (xen_start_info->mfn_list < __START_KERNEL_map ++ && e820_table_end <= xen_start_info->first_p2m_pfn ++ && top > xen_start_info->first_p2m_pfn) ++ top += xen_start_info->nr_p2m_frames; ++ if (paddr < (top << PAGE_SHIFT)) ++ readonly = 1; ++ } + /* Make old page tables read-only. */ + if (!xen_feature(XENFEAT_writable_page_tables) + && (paddr >= (xen_start_info->pt_base - __START_KERNEL_map)) + && (paddr < (e820_table_end << PAGE_SHIFT))) + readonly = 1; ++ /* Make P->M table (and its page tables) read-only. */ ++ if (!xen_feature(XENFEAT_writable_page_tables) ++ && xen_start_info->mfn_list < __START_KERNEL_map ++ && paddr >= (xen_start_info->first_p2m_pfn << PAGE_SHIFT) ++ && paddr < (xen_start_info->first_p2m_pfn ++ + xen_start_info->nr_p2m_frames) << PAGE_SHIFT) ++ readonly = 1; + + /* + * No need for writable mapping of kernel image. This also ensures that +@@ -718,6 +742,12 @@ void __init xen_init_pt(void) + (PTRS_PER_PUD - pud_index(__START_KERNEL_map)) + * sizeof(*level3_kernel_pgt)); + ++ /* Copy the initial P->M table mappings if necessary. */ ++ addr = pgd_index(xen_start_info->mfn_list); ++ if (addr < pgd_index(__START_KERNEL_map)) ++ init_level4_pgt[addr] = ++ ((pgd_t *)xen_start_info->pt_base)[addr]; ++ + /* Do an early initialization of the fixmap area. */ + addr = __fix_to_virt(FIX_EARLYCON_MEM_BASE); + if (pud_present(level3_kernel_pgt[pud_index(addr)])) { +@@ -749,22 +779,27 @@ void __init xen_init_pt(void) + void __init xen_finish_init_mapping(void) + { + unsigned long start, end; ++ struct mmuext_op mmuext; + + /* Re-vector virtual addresses pointing into the initial + mapping to the just-established permanent ones. */ + xen_start_info = __va(__pa(xen_start_info)); + xen_start_info->pt_base = (unsigned long) + __va(__pa(xen_start_info->pt_base)); +- if (!xen_feature(XENFEAT_auto_translated_physmap)) { ++ if (!xen_feature(XENFEAT_auto_translated_physmap) ++ && xen_start_info->mfn_list >= __START_KERNEL_map) + phys_to_machine_mapping = + __va(__pa(xen_start_info->mfn_list)); +- xen_start_info->mfn_list = (unsigned long) +- phys_to_machine_mapping; +- } + if (xen_start_info->mod_start) + xen_start_info->mod_start = (unsigned long) + __va(__pa(xen_start_info->mod_start)); + ++ /* Unpin the no longer used Xen provided page tables. */ ++ mmuext.cmd = MMUEXT_UNPIN_TABLE; ++ mmuext.arg1.mfn = virt_to_mfn(xen_start_info->pt_base); ++ if (HYPERVISOR_mmuext_op(&mmuext, 1, NULL, DOMID_SELF)) ++ BUG(); ++ + /* Destroy the Xen-created mappings beyond the kernel image. */ + start = PAGE_ALIGN(_brk_end); + end = __START_KERNEL_map + (e820_table_start << PAGE_SHIFT); +--- sle11sp1-2010-03-22.orig/arch/x86/mm/pageattr-xen.c 2010-03-11 09:32:10.000000000 +0100 ++++ sle11sp1-2010-03-22/arch/x86/mm/pageattr-xen.c 2010-03-11 09:38:40.000000000 +0100 +@@ -1438,7 +1438,7 @@ static void __make_page_writable(unsigne + + pte = lookup_address(va, &level); + BUG_ON(!pte || level != PG_LEVEL_4K); +- if (HYPERVISOR_update_va_mapping(va, pte_mkwrite(*pte), 0)) ++ if (HYPERVISOR_update_va_mapping(va, pte_mkwrite(*pte), UVMF_INVLPG)) + BUG(); + if (in_secondary_range(va)) { + unsigned long pfn = pte_pfn(*pte); +--- sle11sp1-2010-03-22.orig/arch/x86/mm/pgtable-xen.c 2010-03-22 13:00:09.000000000 +0100 ++++ sle11sp1-2010-03-22/arch/x86/mm/pgtable-xen.c 2010-03-22 13:00:27.000000000 +0100 +@@ -343,7 +343,7 @@ void __init xen_init_pgd_pin(void) + if (PTRS_PER_PUD > 1) /* not folded */ + SetPagePinned(virt_to_page(pud)); + for (u = 0; u < PTRS_PER_PUD; u++, pud++) { +- if (!pud_present(*pud)) ++ if (!pud_present(*pud) || pud_large(*pud)) + continue; + pmd = pmd_offset(pud, 0); + if (PTRS_PER_PMD > 1) /* not folded */ +@@ -354,7 +354,7 @@ void __init xen_init_pgd_pin(void) + && m >= pmd_index(HYPERVISOR_VIRT_START)) + continue; + #endif +- if (!pmd_present(*pmd)) ++ if (!pmd_present(*pmd) || pmd_large(*pmd)) + continue; + SetPagePinned(pmd_page(*pmd)); + } +--- sle11sp1-2010-03-22.orig/arch/x86/mm/pgtable_32-xen.c 2009-11-06 10:52:02.000000000 +0100 ++++ sle11sp1-2010-03-22/arch/x86/mm/pgtable_32-xen.c 2009-12-04 12:12:10.000000000 +0100 +@@ -175,6 +175,6 @@ void make_lowmem_page_writable(void *va, + pte = lookup_address((unsigned long)va, &level); + BUG_ON(!pte || level != PG_LEVEL_4K || !pte_present(*pte)); + rc = HYPERVISOR_update_va_mapping( +- (unsigned long)va, pte_mkwrite(*pte), 0); ++ (unsigned long)va, pte_mkwrite(*pte), UVMF_INVLPG); + BUG_ON(rc); + } diff --git a/xen-x86_64-pgd-alloc-order b/xen-x86_64-pgd-alloc-order new file mode 100644 index 0000000..28ed242 --- /dev/null +++ b/xen-x86_64-pgd-alloc-order @@ -0,0 +1,337 @@ +From: jbeulich@novell.com +Subject: don't require order-1 allocations for pgd-s +Patch-mainline: obsolete + +At the same time remove the useless user mode pair of init_level4_pgt. + +--- sle11sp1-2010-03-22.orig/arch/x86/include/mach-xen/asm/hypervisor.h 2009-11-23 10:55:40.000000000 +0100 ++++ sle11sp1-2010-03-22/arch/x86/include/mach-xen/asm/hypervisor.h 2009-12-04 12:11:43.000000000 +0100 +@@ -104,8 +104,8 @@ void do_hypervisor_callback(struct pt_re + * be MACHINE addresses. + */ + +-void xen_pt_switch(unsigned long ptr); +-void xen_new_user_pt(unsigned long ptr); /* x86_64 only */ ++void xen_pt_switch(pgd_t *); ++void xen_new_user_pt(pgd_t *); /* x86_64 only */ + void xen_load_gs(unsigned int selector); /* x86_64 only */ + void xen_tlb_flush(void); + void xen_invlpg(unsigned long ptr); +@@ -113,7 +113,7 @@ void xen_invlpg(unsigned long ptr); + void xen_l1_entry_update(pte_t *ptr, pte_t val); + void xen_l2_entry_update(pmd_t *ptr, pmd_t val); + void xen_l3_entry_update(pud_t *ptr, pud_t val); /* x86_64/PAE */ +-void xen_l4_entry_update(pgd_t *ptr, int user, pgd_t val); /* x86_64 only */ ++void xen_l4_entry_update(pgd_t *ptr, pgd_t val); /* x86_64 only */ + void xen_pgd_pin(pgd_t *); + void xen_pgd_unpin(pgd_t *); + +--- sle11sp1-2010-03-22.orig/arch/x86/include/mach-xen/asm/mmu_context.h 2009-11-06 10:52:22.000000000 +0100 ++++ sle11sp1-2010-03-22/arch/x86/include/mach-xen/asm/mmu_context.h 2009-12-04 12:11:43.000000000 +0100 +@@ -82,6 +82,9 @@ static inline void switch_mm(struct mm_s + { + unsigned cpu = smp_processor_id(); + struct mmuext_op _op[2 + (sizeof(long) > 4)], *op = _op; ++#ifdef CONFIG_X86_64 ++ pgd_t *upgd; ++#endif + + if (likely(prev != next)) { + BUG_ON(!xen_feature(XENFEAT_writable_page_tables) && +@@ -100,10 +103,11 @@ static inline void switch_mm(struct mm_s + op->arg1.mfn = virt_to_mfn(next->pgd); + op++; + +- /* xen_new_user_pt(__pa(__user_pgd(next->pgd))) */ ++ /* xen_new_user_pt(next->pgd) */ + #ifdef CONFIG_X86_64 + op->cmd = MMUEXT_NEW_USER_BASEPTR; +- op->arg1.mfn = virt_to_mfn(__user_pgd(next->pgd)); ++ upgd = __user_pgd(next->pgd); ++ op->arg1.mfn = likely(upgd) ? virt_to_mfn(upgd) : 0; + op++; + #endif + +@@ -131,7 +135,7 @@ static inline void switch_mm(struct mm_s + * to make sure to use no freed page tables. + */ + load_cr3(next->pgd); +- xen_new_user_pt(__pa(__user_pgd(next->pgd))); ++ xen_new_user_pt(next->pgd); + load_LDT_nolock(&next->context); + } + } +--- sle11sp1-2010-03-22.orig/arch/x86/include/mach-xen/asm/pgalloc.h 2010-03-22 12:59:30.000000000 +0100 ++++ sle11sp1-2010-03-22/arch/x86/include/mach-xen/asm/pgalloc.h 2010-03-22 13:00:16.000000000 +0100 +@@ -123,15 +123,13 @@ static inline void pud_populate(struct m + #endif /* CONFIG_X86_PAE */ + + #if PAGETABLE_LEVELS > 3 +-#define __user_pgd(pgd) ((pgd) + PTRS_PER_PGD) +- + static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud) + { + pgd_t ent = __pgd(_PAGE_TABLE | __pa(pud)); + + paravirt_alloc_pud(mm, __pa(pud) >> PAGE_SHIFT); + if (unlikely(PagePinned(virt_to_page(pgd)))) +- xen_l4_entry_update(pgd, 1, ent); ++ xen_l4_entry_update(pgd, ent); + else + *__user_pgd(pgd) = *pgd = ent; + } +--- sle11sp1-2010-03-22.orig/arch/x86/include/mach-xen/asm/pgtable_64.h 2009-11-06 11:12:01.000000000 +0100 ++++ sle11sp1-2010-03-22/arch/x86/include/mach-xen/asm/pgtable_64.h 2009-12-04 12:11:43.000000000 +0100 +@@ -100,18 +100,25 @@ static inline void xen_set_pud(pud_t *pu + : (void)(*__pudp = xen_make_pud(0)); \ + }) + +-#define __user_pgd(pgd) ((pgd) + PTRS_PER_PGD) ++static inline pgd_t *__user_pgd(pgd_t *pgd) ++{ ++ if (unlikely(((unsigned long)pgd & PAGE_MASK) ++ == (unsigned long)init_level4_pgt)) ++ return NULL; ++ return (pgd_t *)(virt_to_page(pgd)->index ++ + ((unsigned long)pgd & ~PAGE_MASK)); ++} + + static inline void xen_set_pgd(pgd_t *pgdp, pgd_t pgd) + { +- xen_l4_entry_update(pgdp, 0, pgd); ++ xen_l4_entry_update(pgdp, pgd); + } + + #define xen_pgd_clear(pgd) \ + ({ \ + pgd_t *__pgdp = (pgd); \ + PagePinned(virt_to_page(__pgdp)) \ +- ? xen_l4_entry_update(__pgdp, 1, xen_make_pgd(0)) \ ++ ? xen_l4_entry_update(__pgdp, xen_make_pgd(0)) \ + : (void)(*__user_pgd(__pgdp) = *__pgdp = xen_make_pgd(0)); \ + }) + +--- sle11sp1-2010-03-22.orig/arch/x86/kernel/cpu/common-xen.c 2009-11-06 11:12:01.000000000 +0100 ++++ sle11sp1-2010-03-22/arch/x86/kernel/cpu/common-xen.c 2010-01-18 17:14:45.000000000 +0100 +@@ -1026,8 +1026,7 @@ DEFINE_PER_CPU_FIRST(union irq_stack_uni + void xen_switch_pt(void) + { + #ifdef CONFIG_XEN +- xen_pt_switch(__pa_symbol(init_level4_pgt)); +- xen_new_user_pt(__pa_symbol(__user_pgd(init_level4_pgt))); ++ xen_pt_switch(init_level4_pgt); + #endif + } + +--- sle11sp1-2010-03-22.orig/arch/x86/kernel/head_64-xen.S 2009-12-04 14:37:14.000000000 +0100 ++++ sle11sp1-2010-03-22/arch/x86/kernel/head_64-xen.S 2009-12-04 14:37:53.000000000 +0100 +@@ -56,14 +56,6 @@ ENTRY(name) + __PAGE_ALIGNED_BSS + NEXT_PAGE(init_level4_pgt) + .fill 512,8,0 +- /* +- * We update two pgd entries to make kernel and user pgd consistent +- * at pgd_populate(). It can be used for kernel modules. So we place +- * this page here for those cases to avoid memory corruption. +- * We also use this page to establish the initial mapping for the +- * vsyscall area. +- */ +- .fill 512,8,0 + + NEXT_PAGE(level3_kernel_pgt) + .fill 512,8,0 +--- sle11sp1-2010-03-22.orig/arch/x86/mm/hypervisor.c 2010-01-05 16:47:51.000000000 +0100 ++++ sle11sp1-2010-03-22/arch/x86/mm/hypervisor.c 2010-01-05 16:47:55.000000000 +0100 +@@ -525,7 +525,7 @@ void xen_l3_entry_update(pud_t *ptr, pud + #endif + + #ifdef CONFIG_X86_64 +-void xen_l4_entry_update(pgd_t *ptr, int user, pgd_t val) ++void xen_l4_entry_update(pgd_t *ptr, pgd_t val) + { + mmu_update_t u[2]; + struct page *page = NULL; +@@ -538,8 +538,11 @@ void xen_l4_entry_update(pgd_t *ptr, int + } + u[0].ptr = virt_to_machine(ptr); + u[0].val = __pgd_val(val); +- if (user) { +- u[1].ptr = virt_to_machine(__user_pgd(ptr)); ++ if (((unsigned long)ptr & ~PAGE_MASK) ++ <= pgd_index(TASK_SIZE_MAX) * sizeof(*ptr)) { ++ ptr = __user_pgd(ptr); ++ BUG_ON(!ptr); ++ u[1].ptr = virt_to_machine(ptr); + u[1].val = __pgd_val(val); + do_lN_entry_update(u, 2, page); + } else +@@ -547,21 +550,25 @@ void xen_l4_entry_update(pgd_t *ptr, int + } + #endif /* CONFIG_X86_64 */ + +-void xen_pt_switch(unsigned long ptr) ++#ifdef CONFIG_X86_64 ++void xen_pt_switch(pgd_t *pgd) + { + struct mmuext_op op; + op.cmd = MMUEXT_NEW_BASEPTR; +- op.arg1.mfn = pfn_to_mfn(ptr >> PAGE_SHIFT); ++ op.arg1.mfn = virt_to_mfn(pgd); + BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0); + } + +-void xen_new_user_pt(unsigned long ptr) ++void xen_new_user_pt(pgd_t *pgd) + { + struct mmuext_op op; ++ ++ pgd = __user_pgd(pgd); + op.cmd = MMUEXT_NEW_USER_BASEPTR; +- op.arg1.mfn = pfn_to_mfn(ptr >> PAGE_SHIFT); ++ op.arg1.mfn = pgd ? virt_to_mfn(pgd) : 0; + BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0); + } ++#endif + + void xen_tlb_flush(void) + { +@@ -638,7 +645,14 @@ void xen_pgd_pin(pgd_t *pgd) + op[0].arg1.mfn = virt_to_mfn(pgd); + #ifdef CONFIG_X86_64 + op[1].cmd = op[0].cmd = MMUEXT_PIN_L4_TABLE; +- op[1].arg1.mfn = virt_to_mfn(__user_pgd(pgd)); ++ pgd = __user_pgd(pgd); ++ if (pgd) ++ op[1].arg1.mfn = virt_to_mfn(pgd); ++ else { ++ op[1].cmd = MMUEXT_PIN_L3_TABLE; ++ op[1].arg1.mfn = pfn_to_mfn(__pa_symbol(level3_user_pgt) ++ >> PAGE_SHIFT); ++ } + #endif + if (HYPERVISOR_mmuext_op(op, NR_PGD_PIN_OPS, NULL, DOMID_SELF) < 0) + BUG(); +@@ -651,8 +665,10 @@ void xen_pgd_unpin(pgd_t *pgd) + op[0].cmd = MMUEXT_UNPIN_TABLE; + op[0].arg1.mfn = virt_to_mfn(pgd); + #ifdef CONFIG_X86_64 ++ pgd = __user_pgd(pgd); ++ BUG_ON(!pgd); + op[1].cmd = MMUEXT_UNPIN_TABLE; +- op[1].arg1.mfn = virt_to_mfn(__user_pgd(pgd)); ++ op[1].arg1.mfn = virt_to_mfn(pgd); + #endif + if (HYPERVISOR_mmuext_op(op, NR_PGD_PIN_OPS, NULL, DOMID_SELF) < 0) + BUG(); +--- sle11sp1-2010-03-22.orig/arch/x86/mm/init_64-xen.c 2009-10-13 17:25:37.000000000 +0200 ++++ sle11sp1-2010-03-22/arch/x86/mm/init_64-xen.c 2009-12-04 12:11:43.000000000 +0100 +@@ -718,9 +718,6 @@ void __init xen_init_pt(void) + (PTRS_PER_PUD - pud_index(__START_KERNEL_map)) + * sizeof(*level3_kernel_pgt)); + +- __user_pgd(init_level4_pgt)[pgd_index(VSYSCALL_START)] = +- __pgd(__pa_symbol(level3_user_pgt) | _PAGE_TABLE); +- + /* Do an early initialization of the fixmap area. */ + addr = __fix_to_virt(FIX_EARLYCON_MEM_BASE); + if (pud_present(level3_kernel_pgt[pud_index(addr)])) { +@@ -736,8 +733,6 @@ void __init xen_init_pt(void) + + early_make_page_readonly(init_level4_pgt, + XENFEAT_writable_page_tables); +- early_make_page_readonly(__user_pgd(init_level4_pgt), +- XENFEAT_writable_page_tables); + early_make_page_readonly(level3_kernel_pgt, + XENFEAT_writable_page_tables); + early_make_page_readonly(level3_user_pgt, +--- sle11sp1-2010-03-22.orig/arch/x86/mm/pgtable-xen.c 2010-03-22 13:00:04.000000000 +0100 ++++ sle11sp1-2010-03-22/arch/x86/mm/pgtable-xen.c 2010-03-22 13:00:09.000000000 +0100 +@@ -290,9 +290,11 @@ static void pgd_walk(pgd_t *pgd_base, pg + BUG(); + seq = 0; + } ++ pgd = __user_pgd(pgd_base); ++ BUG_ON(!pgd); + MULTI_update_va_mapping(mcl + seq, +- (unsigned long)__user_pgd(pgd_base), +- pfn_pte(virt_to_phys(__user_pgd(pgd_base))>>PAGE_SHIFT, flags), ++ (unsigned long)pgd, ++ pfn_pte(virt_to_phys(pgd)>>PAGE_SHIFT, flags), + 0); + MULTI_update_va_mapping(mcl + seq + 1, + (unsigned long)pgd_base, +@@ -680,12 +682,29 @@ static void pgd_prepopulate_pmd(struct m + } + } + ++static inline pgd_t *user_pgd_alloc(pgd_t *pgd) ++{ + #ifdef CONFIG_X86_64 +-/* We allocate two contiguous pages for kernel and user. */ +-#define PGD_ORDER 1 +-#else +-#define PGD_ORDER 0 ++ if (pgd) { ++ pgd_t *upgd = (void *)__get_free_page(PGALLOC_GFP); ++ ++ if (upgd) ++ virt_to_page(pgd)->index = (long)upgd; ++ else { ++ free_page((unsigned long)pgd); ++ pgd = NULL; ++ } ++ } ++#endif ++ return pgd; ++} ++ ++static inline void user_pgd_free(pgd_t *pgd) ++{ ++#ifdef CONFIG_X86_64 ++ free_page(virt_to_page(pgd)->index); + #endif ++} + + pgd_t *pgd_alloc(struct mm_struct *mm) + { +@@ -693,7 +712,7 @@ pgd_t *pgd_alloc(struct mm_struct *mm) + pmd_t *pmds[PREALLOCATED_PMDS]; + unsigned long flags; + +- pgd = (pgd_t *)__get_free_pages(PGALLOC_GFP, PGD_ORDER); ++ pgd = user_pgd_alloc((void *)__get_free_page(PGALLOC_GFP)); + + if (pgd == NULL) + goto out; +@@ -732,7 +751,8 @@ pgd_t *pgd_alloc(struct mm_struct *mm) + out_free_pmds: + free_pmds(pmds, mm, !xen_feature(XENFEAT_pae_pgdir_above_4gb)); + out_free_pgd: +- free_pages((unsigned long)pgd, PGD_ORDER); ++ user_pgd_free(pgd); ++ free_page((unsigned long)pgd); + out: + return NULL; + } +@@ -751,7 +771,8 @@ void pgd_free(struct mm_struct *mm, pgd_ + + pgd_mop_up_pmds(mm, pgd); + paravirt_pgd_free(mm, pgd); +- free_pages((unsigned long)pgd, PGD_ORDER); ++ user_pgd_free(pgd); ++ free_page((unsigned long)pgd); + } + + /* blktap and gntdev need this, as otherwise they would implicitly (and +--- sle11sp1-2010-03-22.orig/drivers/xen/core/machine_reboot.c 2009-12-18 14:15:17.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/xen/core/machine_reboot.c 2009-12-18 14:15:58.000000000 +0100 +@@ -188,8 +188,7 @@ static int take_machine_down(void *_susp + * in fast-suspend mode as that implies a new enough Xen. + */ + if (!suspend->fast_suspend) +- xen_new_user_pt(__pa(__user_pgd( +- current->active_mm->pgd))); ++ xen_new_user_pt(current->active_mm->pgd); + #endif + } + diff --git a/xen-x86_64-pgd-pin b/xen-x86_64-pgd-pin new file mode 100644 index 0000000..4980da0 --- /dev/null +++ b/xen-x86_64-pgd-pin @@ -0,0 +1,111 @@ +From: jbeulich@novell.com +Subject: make pinning of pgd pairs transparent to callers +Patch-mainline: obsolete + +--- sle11sp1-2010-03-22.orig/arch/x86/include/mach-xen/asm/hypervisor.h 2009-11-23 10:53:45.000000000 +0100 ++++ sle11sp1-2010-03-22/arch/x86/include/mach-xen/asm/hypervisor.h 2009-11-23 10:55:40.000000000 +0100 +@@ -114,8 +114,8 @@ void xen_l1_entry_update(pte_t *ptr, pte + void xen_l2_entry_update(pmd_t *ptr, pmd_t val); + void xen_l3_entry_update(pud_t *ptr, pud_t val); /* x86_64/PAE */ + void xen_l4_entry_update(pgd_t *ptr, int user, pgd_t val); /* x86_64 only */ +-void xen_pgd_pin(unsigned long ptr); +-void xen_pgd_unpin(unsigned long ptr); ++void xen_pgd_pin(pgd_t *); ++void xen_pgd_unpin(pgd_t *); + + void xen_init_pgd_pin(void); + +--- sle11sp1-2010-03-22.orig/arch/x86/mm/hypervisor.c 2010-01-05 16:47:18.000000000 +0100 ++++ sle11sp1-2010-03-22/arch/x86/mm/hypervisor.c 2010-01-05 16:47:51.000000000 +0100 +@@ -624,26 +624,38 @@ EXPORT_SYMBOL_GPL(xen_invlpg_mask); + + #endif /* CONFIG_SMP */ + +-void xen_pgd_pin(unsigned long ptr) +-{ +- struct mmuext_op op; + #ifdef CONFIG_X86_64 +- op.cmd = MMUEXT_PIN_L4_TABLE; +-#elif defined(CONFIG_X86_PAE) +- op.cmd = MMUEXT_PIN_L3_TABLE; ++#define NR_PGD_PIN_OPS 2 + #else +- op.cmd = MMUEXT_PIN_L2_TABLE; ++#define NR_PGD_PIN_OPS 1 + #endif +- op.arg1.mfn = pfn_to_mfn(ptr >> PAGE_SHIFT); +- BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0); ++ ++void xen_pgd_pin(pgd_t *pgd) ++{ ++ struct mmuext_op op[NR_PGD_PIN_OPS]; ++ ++ op[0].cmd = MMUEXT_PIN_L3_TABLE; ++ op[0].arg1.mfn = virt_to_mfn(pgd); ++#ifdef CONFIG_X86_64 ++ op[1].cmd = op[0].cmd = MMUEXT_PIN_L4_TABLE; ++ op[1].arg1.mfn = virt_to_mfn(__user_pgd(pgd)); ++#endif ++ if (HYPERVISOR_mmuext_op(op, NR_PGD_PIN_OPS, NULL, DOMID_SELF) < 0) ++ BUG(); + } + +-void xen_pgd_unpin(unsigned long ptr) ++void xen_pgd_unpin(pgd_t *pgd) + { +- struct mmuext_op op; +- op.cmd = MMUEXT_UNPIN_TABLE; +- op.arg1.mfn = pfn_to_mfn(ptr >> PAGE_SHIFT); +- BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0); ++ struct mmuext_op op[NR_PGD_PIN_OPS]; ++ ++ op[0].cmd = MMUEXT_UNPIN_TABLE; ++ op[0].arg1.mfn = virt_to_mfn(pgd); ++#ifdef CONFIG_X86_64 ++ op[1].cmd = MMUEXT_UNPIN_TABLE; ++ op[1].arg1.mfn = virt_to_mfn(__user_pgd(pgd)); ++#endif ++ if (HYPERVISOR_mmuext_op(op, NR_PGD_PIN_OPS, NULL, DOMID_SELF) < 0) ++ BUG(); + } + + void xen_set_ldt(const void *ptr, unsigned int ents) +--- sle11sp1-2010-03-22.orig/arch/x86/mm/init_64-xen.c 2009-11-06 11:12:01.000000000 +0100 ++++ sle11sp1-2010-03-22/arch/x86/mm/init_64-xen.c 2009-10-13 17:25:37.000000000 +0200 +@@ -747,10 +747,8 @@ void __init xen_init_pt(void) + early_make_page_readonly(level1_fixmap_pgt, + XENFEAT_writable_page_tables); + +- if (!xen_feature(XENFEAT_writable_page_tables)) { +- xen_pgd_pin(__pa_symbol(init_level4_pgt)); +- xen_pgd_pin(__pa_symbol(__user_pgd(init_level4_pgt))); +- } ++ if (!xen_feature(XENFEAT_writable_page_tables)) ++ xen_pgd_pin(init_level4_pgt); + } + + void __init xen_finish_init_mapping(void) +--- sle11sp1-2010-03-22.orig/arch/x86/mm/pgtable-xen.c 2010-03-22 12:59:47.000000000 +0100 ++++ sle11sp1-2010-03-22/arch/x86/mm/pgtable-xen.c 2010-03-22 13:00:04.000000000 +0100 +@@ -367,19 +367,13 @@ static void __pgd_pin(pgd_t *pgd) + { + pgd_walk(pgd, PAGE_KERNEL_RO); + kmap_flush_unused(); +- xen_pgd_pin(__pa(pgd)); /* kernel */ +-#ifdef CONFIG_X86_64 +- xen_pgd_pin(__pa(__user_pgd(pgd))); /* user */ +-#endif ++ xen_pgd_pin(pgd); + SetPagePinned(virt_to_page(pgd)); + } + + static void __pgd_unpin(pgd_t *pgd) + { +- xen_pgd_unpin(__pa(pgd)); +-#ifdef CONFIG_X86_64 +- xen_pgd_unpin(__pa(__user_pgd(pgd))); +-#endif ++ xen_pgd_unpin(pgd); + pgd_walk(pgd, PAGE_KERNEL); + ClearPagePinned(virt_to_page(pgd)); + } diff --git a/xen3-auto-arch-i386.diff b/xen3-auto-arch-i386.diff new file mode 100644 index 0000000..536fb3f --- /dev/null +++ b/xen3-auto-arch-i386.diff @@ -0,0 +1,193 @@ +Subject: xen3 arch-i386 +From: http://xenbits.xensource.com/linux-2.6.18-xen.hg (tip 1011:11175e60d393) +Patch-mainline: obsolete +Acked-by: jbeulich@novell.com + +--- sle11sp1-2010-03-01.orig/arch/x86/kernel/asm-offsets_32.c 2010-03-01 14:09:07.000000000 +0100 ++++ sle11sp1-2010-03-01/arch/x86/kernel/asm-offsets_32.c 2009-12-04 10:44:46.000000000 +0100 +@@ -93,9 +93,14 @@ void foo(void) + OFFSET(pbe_orig_address, pbe, orig_address); + OFFSET(pbe_next, pbe, next); + ++#ifndef CONFIG_X86_NO_TSS + /* Offset from the sysenter stack to tss.sp0 */ +- DEFINE(TSS_sysenter_sp0, offsetof(struct tss_struct, x86_tss.sp0) - ++ DEFINE(SYSENTER_stack_sp0, offsetof(struct tss_struct, x86_tss.sp0) - + sizeof(struct tss_struct)); ++#else ++ /* sysenter stack points directly to sp0 */ ++ DEFINE(SYSENTER_stack_sp0, 0); ++#endif + + DEFINE(PAGE_SIZE_asm, PAGE_SIZE); + DEFINE(PAGE_SHIFT_asm, PAGE_SHIFT); +--- sle11sp1-2010-03-01.orig/arch/x86/kernel/entry_32.S 2010-03-01 14:09:07.000000000 +0100 ++++ sle11sp1-2010-03-01/arch/x86/kernel/entry_32.S 2009-12-04 10:44:46.000000000 +0100 +@@ -393,7 +393,7 @@ ENTRY(ia32_sysenter_target) + CFI_SIGNAL_FRAME + CFI_DEF_CFA esp, 0 + CFI_REGISTER esp, ebp +- movl TSS_sysenter_sp0(%esp),%esp ++ movl SYSENTER_stack_sp0(%esp),%esp + sysenter_past_esp: + /* + * Interrupts are disabled here, but we can't trace it until +@@ -1325,7 +1325,7 @@ END(page_fault) + * that sets up the real kernel stack. Check here, since we can't + * allow the wrong stack to be used. + * +- * "TSS_sysenter_sp0+12" is because the NMI/debug handler will have ++ * "SYSENTER_stack_sp0+12" is because the NMI/debug handler will have + * already pushed 3 words if it hits on the sysenter instruction: + * eflags, cs and eip. + * +@@ -1337,7 +1337,7 @@ END(page_fault) + cmpw $__KERNEL_CS, 4(%esp) + jne \ok + \label: +- movl TSS_sysenter_sp0 + \offset(%esp), %esp ++ movl SYSENTER_stack_sp0 + \offset(%esp), %esp + CFI_DEF_CFA esp, 0 + CFI_UNDEFINED eip + pushfl +--- sle11sp1-2010-03-01.orig/arch/x86/kernel/machine_kexec_32.c 2009-04-21 10:33:15.000000000 +0200 ++++ sle11sp1-2010-03-01/arch/x86/kernel/machine_kexec_32.c 2009-12-04 10:44:46.000000000 +0100 +@@ -26,6 +26,10 @@ + #include + #include + ++#ifdef CONFIG_XEN ++#include ++#endif ++ + static void machine_kexec_free_page_tables(struct kimage *image) + { + free_page((unsigned long)image->arch.pgd); +@@ -96,6 +100,55 @@ static void machine_kexec_prepare_page_t + __pa(control_page), __pa(control_page)); + } + ++#ifdef CONFIG_XEN ++ ++#define __ma(x) (pfn_to_mfn(__pa((x)) >> PAGE_SHIFT) << PAGE_SHIFT) ++ ++#if PAGES_NR > KEXEC_XEN_NO_PAGES ++#error PAGES_NR is greater than KEXEC_XEN_NO_PAGES - Xen support will break ++#endif ++ ++#if PA_CONTROL_PAGE != 0 ++#error PA_CONTROL_PAGE is non zero - Xen support will break ++#endif ++ ++void machine_kexec_setup_load_arg(xen_kexec_image_t *xki, struct kimage *image) ++{ ++ void *control_page; ++ ++ memset(xki->page_list, 0, sizeof(xki->page_list)); ++ ++ control_page = page_address(image->control_code_page); ++ memcpy(control_page, relocate_kernel, PAGE_SIZE); ++ ++ xki->page_list[PA_CONTROL_PAGE] = __ma(control_page); ++ xki->page_list[PA_PGD] = __ma(kexec_pgd); ++#ifdef CONFIG_X86_PAE ++ xki->page_list[PA_PMD_0] = __ma(kexec_pmd0); ++ xki->page_list[PA_PMD_1] = __ma(kexec_pmd1); ++#endif ++ xki->page_list[PA_PTE_0] = __ma(kexec_pte0); ++ xki->page_list[PA_PTE_1] = __ma(kexec_pte1); ++ ++} ++ ++int __init machine_kexec_setup_resources(struct resource *hypervisor, ++ struct resource *phys_cpus, ++ int nr_phys_cpus) ++{ ++ int k; ++ ++ /* The per-cpu crash note resources belong to the hypervisor resource */ ++ for (k = 0; k < nr_phys_cpus; k++) ++ request_resource(hypervisor, phys_cpus + k); ++ ++ return 0; ++} ++ ++void machine_kexec_register_resources(struct resource *res) { ; } ++ ++#endif /* CONFIG_XEN */ ++ + /* + * A architecture hook called to validate the + * proposed image and prepare the control pages +@@ -135,6 +188,7 @@ void machine_kexec_cleanup(struct kimage + machine_kexec_free_page_tables(image); + } + ++#ifndef CONFIG_XEN + /* + * Do not allocate memory (or fail in any way) in machine_kexec(). + * We are past the point of no return, committed to rebooting now. +@@ -199,6 +253,7 @@ void machine_kexec(struct kimage *image) + + __ftrace_enabled_restore(save_ftrace_enabled); + } ++#endif + + void arch_crash_save_vmcoreinfo(void) + { +--- sle11sp1-2010-03-01.orig/arch/x86/kernel/vm86_32.c 2010-03-01 14:09:07.000000000 +0100 ++++ sle11sp1-2010-03-01/arch/x86/kernel/vm86_32.c 2009-12-04 10:44:46.000000000 +0100 +@@ -125,7 +125,9 @@ static int copy_vm86_regs_from_user(stru + + struct pt_regs *save_v86_state(struct kernel_vm86_regs *regs) + { ++#ifndef CONFIG_X86_NO_TSS + struct tss_struct *tss; ++#endif + struct pt_regs *ret; + unsigned long tmp; + +@@ -148,12 +150,16 @@ struct pt_regs *save_v86_state(struct ke + do_exit(SIGSEGV); + } + ++#ifndef CONFIG_X86_NO_TSS + tss = &per_cpu(init_tss, get_cpu()); ++#endif + current->thread.sp0 = current->thread.saved_sp0; + current->thread.sysenter_cs = __KERNEL_CS; + load_sp0(tss, ¤t->thread); + current->thread.saved_sp0 = 0; ++#ifndef CONFIG_X86_NO_TSS + put_cpu(); ++#endif + + ret = KVM86->regs32; + +@@ -280,7 +286,9 @@ out: + + static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk) + { ++#ifndef CONFIG_X86_NO_TSS + struct tss_struct *tss; ++#endif + /* + * make sure the vm86() system call doesn't try to do anything silly + */ +@@ -324,12 +332,16 @@ static void do_sys_vm86(struct kernel_vm + tsk->thread.saved_fs = info->regs32->fs; + tsk->thread.saved_gs = get_user_gs(info->regs32); + ++#ifndef CONFIG_X86_NO_TSS + tss = &per_cpu(init_tss, get_cpu()); ++#endif + tsk->thread.sp0 = (unsigned long) &info->VM86_TSS_ESP0; + if (cpu_has_sep) + tsk->thread.sysenter_cs = 0; + load_sp0(tss, &tsk->thread); ++#ifndef CONFIG_X86_NO_TSS + put_cpu(); ++#endif + + tsk->thread.screen_bitmap = info->screen_bitmap; + if (info->flags & VM86_SCREEN_BITMAP) diff --git a/xen3-auto-arch-x86.diff b/xen3-auto-arch-x86.diff new file mode 100644 index 0000000..18734f1 --- /dev/null +++ b/xen3-auto-arch-x86.diff @@ -0,0 +1,464 @@ +Subject: xen3 arch-x86 +From: http://xenbits.xensource.com/linux-2.6.18-xen.hg (tip 1011:11175e60d393) +Patch-mainline: obsolete +Acked-by: jbeulich@novell.com + +List of files that don't require modification anymore (and hence +removed from this patch), for reference and in case upstream wants to +take the forward porting patches: +2.6.26/arch/x86/kernel/crash.c +2.6.30/arch/x86/kernel/acpi/boot.c + +--- sle11sp1-2010-03-29.orig/arch/x86/Makefile 2010-03-29 09:00:35.000000000 +0200 ++++ sle11sp1-2010-03-29/arch/x86/Makefile 2009-12-04 10:44:45.000000000 +0100 +@@ -111,6 +111,10 @@ endif + # prevent gcc from generating any FP code by mistake + KBUILD_CFLAGS += $(call cc-option,-mno-sse -mno-mmx -mno-sse2 -mno-3dnow,) + ++# Xen subarch support ++mflags-$(CONFIG_X86_XEN) := -Iinclude/asm-x86/mach-xen ++mcore-$(CONFIG_X86_XEN) := arch/x86/mach-xen/ ++ + KBUILD_CFLAGS += $(mflags-y) + KBUILD_AFLAGS += $(mflags-y) + +@@ -151,9 +155,26 @@ boot := arch/x86/boot + + BOOT_TARGETS = bzlilo bzdisk fdimage fdimage144 fdimage288 isoimage + +-PHONY += bzImage $(BOOT_TARGETS) ++PHONY += bzImage vmlinuz $(BOOT_TARGETS) ++ ++ifdef CONFIG_XEN ++CPPFLAGS := -D__XEN_INTERFACE_VERSION__=$(CONFIG_XEN_INTERFACE_VERSION) \ ++ -Iinclude$(if $(KBUILD_SRC),2)/asm/mach-xen $(CPPFLAGS) ++ ++ifdef CONFIG_X86_64 ++LDFLAGS_vmlinux := -e startup_64 ++endif + + # Default kernel to build ++all: vmlinuz ++ ++# KBUILD_IMAGE specifies the target image being built ++KBUILD_IMAGE := $(boot)/vmlinuz ++ ++vmlinuz: vmlinux ++ $(Q)$(MAKE) $(build)=$(boot) $(KBUILD_IMAGE) ++else ++# Default kernel to build + all: bzImage + + # KBUILD_IMAGE specify target image being built +@@ -166,6 +187,7 @@ bzImage: vmlinux + + $(BOOT_TARGETS): vmlinux + $(Q)$(MAKE) $(build)=$(boot) $@ ++endif + + PHONY += install + install: +--- sle11sp1-2010-03-29.orig/arch/x86/boot/Makefile 2010-03-29 09:00:35.000000000 +0200 ++++ sle11sp1-2010-03-29/arch/x86/boot/Makefile 2009-12-04 10:44:45.000000000 +0100 +@@ -23,6 +23,7 @@ ROOT_DEV := CURRENT + SVGA_MODE := -DSVGA_MODE=NORMAL_VGA + + targets := vmlinux.bin setup.bin setup.elf bzImage ++targets += vmlinuz vmlinux-stripped + targets += fdimage fdimage144 fdimage288 image.iso mtools.conf + subdir- := compressed + +@@ -195,6 +196,14 @@ bzlilo: $(obj)/bzImage + cp System.map $(INSTALL_PATH)/ + if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi + ++$(obj)/vmlinuz: $(obj)/vmlinux-stripped FORCE ++ $(call if_changed,gzip) ++ @echo 'Kernel: $@ is ready' ' (#'`cat .version`')' ++ ++$(obj)/vmlinux-stripped: OBJCOPYFLAGS := -g --strip-unneeded ++$(obj)/vmlinux-stripped: vmlinux FORCE ++ $(call if_changed,objcopy) ++ + install: + sh $(srctree)/$(src)/install.sh $(KERNELRELEASE) $(obj)/bzImage \ + System.map "$(INSTALL_PATH)" +--- sle11sp1-2010-03-29.orig/arch/x86/kernel/Makefile 2010-03-29 09:00:35.000000000 +0200 ++++ sle11sp1-2010-03-29/arch/x86/kernel/Makefile 2009-12-04 10:44:45.000000000 +0100 +@@ -117,9 +117,12 @@ obj-$(CONFIG_X86_CHECK_BIOS_CORRUPTION) + + obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o + ++obj-$(CONFIG_X86_XEN) += fixup.o ++ + ### + # 64 bit specific files + ifeq ($(CONFIG_X86_64),y) ++ obj-$(CONFIG_X86_XEN_GENAPIC) += genapic_xen_64.o + obj-$(CONFIG_X86_UV) += tlb_uv.o bios_uv.o uv_irq.o uv_sysfs.o uv_time.o + obj-$(CONFIG_X86_PM_TIMER) += pmtimer_64.o + obj-$(CONFIG_AUDIT) += audit_64.o +@@ -130,4 +133,10 @@ ifeq ($(CONFIG_X86_64),y) + + obj-$(CONFIG_PCI_MMCONFIG) += mmconf-fam10h_64.o + obj-y += vsmp_64.o ++ ++ time_64-$(CONFIG_XEN) += time_32.o ++ pci-dma_64-$(CONFIG_XEN) += pci-dma_32.o + endif ++ ++disabled-obj-$(CONFIG_XEN) := i8259_$(BITS).o reboot.o smpboot_$(BITS).o ++%/head_$(BITS).o %/head_$(BITS).s: $(if $(CONFIG_XEN),EXTRA_AFLAGS,dummy) := +--- sle11sp1-2010-03-29.orig/arch/x86/kernel/acpi/Makefile 2010-03-29 09:00:35.000000000 +0200 ++++ sle11sp1-2010-03-29/arch/x86/kernel/acpi/Makefile 2009-12-04 10:44:45.000000000 +0100 +@@ -5,6 +5,9 @@ obj-$(CONFIG_ACPI_SLEEP) += sleep.o wake + + ifneq ($(CONFIG_ACPI_PROCESSOR),) + obj-y += cstate.o processor.o ++ifneq ($(CONFIG_PROCESSOR_EXTERNAL_CONTROL),) ++obj-$(CONFIG_XEN) += processor_extcntl_xen.o ++endif + endif + + $(obj)/wakeup_rm.o: $(obj)/realmode/wakeup.bin +@@ -12,3 +15,4 @@ $(obj)/wakeup_rm.o: $(obj)/realmode/w + $(obj)/realmode/wakeup.bin: FORCE + $(Q)$(MAKE) $(build)=$(obj)/realmode + ++disabled-obj-$(CONFIG_XEN) := cstate.o wakeup_$(BITS).o +--- sle11sp1-2010-03-29.orig/arch/x86/kernel/acpi/processor.c 2010-03-29 09:00:35.000000000 +0200 ++++ sle11sp1-2010-03-29/arch/x86/kernel/acpi/processor.c 2009-12-04 10:44:45.000000000 +0100 +@@ -76,7 +76,18 @@ static void init_intel_pdc(struct acpi_p + /* Initialize _PDC data based on the CPU vendor */ + void arch_acpi_processor_init_pdc(struct acpi_processor *pr) + { ++#ifdef CONFIG_XEN ++ /* ++ * As a work-around, just use cpu0's cpuinfo for all processors. ++ * Further work is required to expose xen hypervisor interface of ++ * getting physical cpuinfo to dom0 kernel and then ++ * arch_acpi_processor_init_pdc can set _PDC parameters according ++ * to Xen's phys information. ++ */ ++ struct cpuinfo_x86 *c = &boot_cpu_data; ++#else + struct cpuinfo_x86 *c = &cpu_data(pr->id); ++#endif + + pr->pdc = NULL; + if (c->x86_vendor == X86_VENDOR_INTEL || +--- sle11sp1-2010-03-29.orig/arch/x86/kernel/cpu/mcheck/Makefile 2010-03-29 09:00:35.000000000 +0200 ++++ sle11sp1-2010-03-29/arch/x86/kernel/cpu/mcheck/Makefile 2010-01-27 14:28:25.000000000 +0100 +@@ -4,6 +4,7 @@ obj-$(CONFIG_X86_ANCIENT_MCE) += winchip + obj-$(CONFIG_X86_MCE_INTEL) += mce_intel.o + obj-$(CONFIG_X86_MCE_XEON75XX) += mce-xeon75xx.o + obj-$(CONFIG_X86_MCE_AMD) += mce_amd.o ++obj-$(CONFIG_X86_XEN_MCE) += mce_dom0.o + obj-$(CONFIG_X86_MCE_THRESHOLD) += threshold.o + obj-$(CONFIG_X86_MCE_INJECT) += mce-inject.o + +--- sle11sp1-2010-03-29.orig/arch/x86/kernel/cpu/mcheck/mce.c 2010-03-29 09:00:35.000000000 +0200 ++++ sle11sp1-2010-03-29/arch/x86/kernel/cpu/mcheck/mce.c 2010-01-27 14:28:39.000000000 +0100 +@@ -1127,8 +1127,15 @@ void mce_log_therm_throt_event(__u64 sta + * Periodic polling timer for "silent" machine check errors. If the + * poller finds an MCE, poll 2x faster. When the poller finds no more + * errors, poll 2x slower (up to check_interval seconds). ++ * ++ * We will disable polling in DOM0 since all CMCI/Polling ++ * mechanism will be done in XEN for Intel CPUs + */ ++#if defined (CONFIG_X86_XEN_MCE) ++static int check_interval = 0; /* disable polling */ ++#else + static int check_interval = 5 * 60; /* 5 minutes */ ++#endif + + static DEFINE_PER_CPU(int, mce_next_interval); /* in jiffies */ + static DEFINE_PER_CPU(struct timer_list, mce_timer); +@@ -1293,6 +1300,7 @@ static int __cpuinit mce_cpu_quirks(stru + + /* This should be disabled by the BIOS, but isn't always */ + if (c->x86_vendor == X86_VENDOR_AMD) { ++#ifndef CONFIG_XEN + if (c->x86 == 15 && banks > 4) { + /* + * disable GART TBL walk error reporting, which +@@ -1301,6 +1309,7 @@ static int __cpuinit mce_cpu_quirks(stru + */ + clear_bit(10, (unsigned long *)&mce_banks[4].ctl); + } ++#endif + if (c->x86 <= 17 && mce_bootlog < 0) { + /* + * Lots of broken BIOS around that don't clear them +@@ -1368,6 +1377,7 @@ static void __cpuinit mce_ancient_init(s + + static void mce_cpu_features(struct cpuinfo_x86 *c) + { ++#ifndef CONFIG_X86_64_XEN + switch (c->x86_vendor) { + case X86_VENDOR_INTEL: + mce_intel_feature_init(c); +@@ -1378,6 +1388,7 @@ static void mce_cpu_features(struct cpui + default: + break; + } ++#endif + } + + static void mce_init_timer(void) +@@ -2064,6 +2075,16 @@ static __init int mce_init_device(void) + register_hotcpu_notifier(&mce_cpu_notifier); + misc_register(&mce_log_device); + ++#ifdef CONFIG_X86_XEN_MCE ++ if (is_initial_xendomain()) { ++ /* Register vIRQ handler for MCE LOG processing */ ++ extern void bind_virq_for_mce(void); ++ ++ printk(KERN_DEBUG "MCE: bind virq for DOM0 logging\n"); ++ bind_virq_for_mce(); ++ } ++#endif ++ + return err; + } + +--- sle11sp1-2010-03-29.orig/arch/x86/kernel/cpu/mtrr/Makefile 2010-03-29 09:00:35.000000000 +0200 ++++ sle11sp1-2010-03-29/arch/x86/kernel/cpu/mtrr/Makefile 2009-12-04 10:44:45.000000000 +0100 +@@ -1,3 +1,4 @@ + obj-y := main.o if.o generic.o state.o cleanup.o + obj-$(CONFIG_X86_32) += amd.o cyrix.o centaur.o + ++obj-$(CONFIG_XEN) := main.o if.o +--- sle11sp1-2010-03-29.orig/arch/x86/lib/Makefile 2010-03-29 09:00:35.000000000 +0200 ++++ sle11sp1-2010-03-29/arch/x86/lib/Makefile 2010-03-29 09:06:18.000000000 +0200 +@@ -28,3 +28,5 @@ else + lib-y += copy_user_64.o rwlock_64.o copy_user_nocache_64.o + lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem_64.o + endif ++ ++lib-$(CONFIG_XEN_SCRUB_PAGES) += scrub.o +--- sle11sp1-2010-03-29.orig/arch/x86/mm/Makefile 2010-03-29 09:00:35.000000000 +0200 ++++ sle11sp1-2010-03-29/arch/x86/mm/Makefile 2009-12-04 10:44:45.000000000 +0100 +@@ -25,4 +25,6 @@ obj-$(CONFIG_NUMA) += numa.o numa_$(BIT + obj-$(CONFIG_K8_NUMA) += k8topology_64.o + obj-$(CONFIG_ACPI_NUMA) += srat_$(BITS).o + ++obj-$(CONFIG_XEN) += hypervisor.o ++ + obj-$(CONFIG_MEMTEST) += memtest.o +--- sle11sp1-2010-03-29.orig/arch/x86/oprofile/Makefile 2010-03-29 09:00:35.000000000 +0200 ++++ sle11sp1-2010-03-29/arch/x86/oprofile/Makefile 2009-12-04 10:44:45.000000000 +0100 +@@ -6,7 +6,14 @@ DRIVER_OBJS = $(addprefix ../../../drive + oprofilefs.o oprofile_stats.o \ + timer_int.o ) + ++ifdef CONFIG_XEN ++XENOPROF_COMMON_OBJS = $(addprefix ../../../drivers/xen/xenoprof/, \ ++ xenoprofile.o) ++oprofile-y := $(DRIVER_OBJS) \ ++ $(XENOPROF_COMMON_OBJS) xenoprof.o ++else + oprofile-y := $(DRIVER_OBJS) init.o backtrace.o + oprofile-$(CONFIG_X86_LOCAL_APIC) += nmi_int.o op_model_amd.o \ + op_model_ppro.o op_model_p4.o + oprofile-$(CONFIG_X86_IO_APIC) += nmi_timer_int.o ++endif +--- sle11sp1-2010-03-29.orig/arch/x86/pci/Makefile 2010-03-29 09:00:35.000000000 +0200 ++++ sle11sp1-2010-03-29/arch/x86/pci/Makefile 2009-12-04 10:44:45.000000000 +0100 +@@ -4,6 +4,9 @@ obj-$(CONFIG_PCI_BIOS) += pcbios.o + obj-$(CONFIG_PCI_MMCONFIG) += mmconfig_$(BITS).o direct.o mmconfig-shared.o + obj-$(CONFIG_PCI_DIRECT) += direct.o + obj-$(CONFIG_PCI_OLPC) += olpc.o ++# pcifront should be after mmconfig.o and direct.o as it should only ++# take over if direct access to the PCI bus is unavailable ++obj-$(CONFIG_XEN_PCIDEV_FRONTEND) += pcifront.o + + obj-y += fixup.o + obj-$(CONFIG_ACPI) += acpi.o +--- sle11sp1-2010-03-29.orig/arch/x86/power/cpu.c 2010-03-29 09:00:35.000000000 +0200 ++++ sle11sp1-2010-03-29/arch/x86/power/cpu.c 2009-12-04 10:44:45.000000000 +0100 +@@ -125,6 +125,7 @@ static void do_fpu_end(void) + + static void fix_processor_context(void) + { ++#ifndef CONFIG_X86_NO_TSS + int cpu = smp_processor_id(); + struct tss_struct *t = &per_cpu(init_tss, cpu); + +@@ -137,7 +138,10 @@ static void fix_processor_context(void) + + #ifdef CONFIG_X86_64 + get_cpu_gdt_table(cpu)[GDT_ENTRY_TSS].type = 9; ++#endif ++#endif + ++#ifdef CONFIG_X86_64 + syscall_init(); /* This sets MSR_*STAR and related */ + #endif + load_TR_desc(); /* This does ltr */ +--- sle11sp1-2010-03-29.orig/arch/x86/include/asm/acpi.h 2010-03-29 09:00:35.000000000 +0200 ++++ sle11sp1-2010-03-29/arch/x86/include/asm/acpi.h 2009-12-04 10:44:45.000000000 +0100 +@@ -30,6 +30,10 @@ + #include + #include + ++#ifdef CONFIG_XEN ++#include ++#endif ++ + #define COMPILER_DEPENDENT_INT64 long long + #define COMPILER_DEPENDENT_UINT64 unsigned long long + +@@ -120,6 +124,27 @@ extern unsigned long acpi_wakeup_address + /* early initialization routine */ + extern void acpi_reserve_bootmem(void); + ++#ifdef CONFIG_XEN ++static inline int acpi_notify_hypervisor_state(u8 sleep_state, ++ u32 pm1a_cnt_val, ++ u32 pm1b_cnt_val) ++{ ++ struct xen_platform_op op = { ++ .cmd = XENPF_enter_acpi_sleep, ++ .interface_version = XENPF_INTERFACE_VERSION, ++ .u = { ++ .enter_acpi_sleep = { ++ .pm1a_cnt_val = pm1a_cnt_val, ++ .pm1b_cnt_val = pm1b_cnt_val, ++ .sleep_state = sleep_state, ++ }, ++ }, ++ }; ++ ++ return HYPERVISOR_platform_op(&op); ++} ++#endif /* CONFIG_XEN */ ++ + /* + * Check if the CPU can handle C2 and deeper + */ +@@ -152,7 +177,9 @@ static inline void disable_acpi(void) { + + #endif /* !CONFIG_ACPI */ + ++#ifndef CONFIG_XEN + #define ARCH_HAS_POWER_INIT 1 ++#endif + + struct bootnode; + +--- sle11sp1-2010-03-29.orig/arch/x86/include/asm/apic.h 2010-03-29 09:00:35.000000000 +0200 ++++ sle11sp1-2010-03-29/arch/x86/include/asm/apic.h 2009-12-04 10:44:45.000000000 +0100 +@@ -15,7 +15,9 @@ + #include + #include + ++#ifndef CONFIG_XEN + #define ARCH_APICTIMER_STOPS_ON_C3 1 ++#endif + + /* + * Debugging macros +--- sle11sp1-2010-03-29.orig/arch/x86/include/asm/kexec.h 2010-03-29 09:00:35.000000000 +0200 ++++ sle11sp1-2010-03-29/arch/x86/include/asm/kexec.h 2009-12-04 10:44:45.000000000 +0100 +@@ -163,6 +163,19 @@ struct kimage_arch { + }; + #endif + ++/* Under Xen we need to work with machine addresses. These macros give the ++ * machine address of a certain page to the generic kexec code instead of ++ * the pseudo physical address which would be given by the default macros. ++ */ ++ ++#ifdef CONFIG_XEN ++#define KEXEC_ARCH_HAS_PAGE_MACROS ++#define kexec_page_to_pfn(page) pfn_to_mfn(page_to_pfn(page)) ++#define kexec_pfn_to_page(pfn) pfn_to_page(mfn_to_pfn(pfn)) ++#define kexec_virt_to_phys(addr) virt_to_machine(addr) ++#define kexec_phys_to_virt(addr) phys_to_virt(machine_to_phys(addr)) ++#endif ++ + #endif /* __ASSEMBLY__ */ + + #endif /* _ASM_X86_KEXEC_H */ +--- sle11sp1-2010-03-29.orig/arch/x86/include/asm/types.h 2010-03-29 09:00:35.000000000 +0200 ++++ sle11sp1-2010-03-29/arch/x86/include/asm/types.h 2010-02-09 16:45:16.000000000 +0100 +@@ -9,7 +9,7 @@ + #ifndef __ASSEMBLY__ + + typedef u64 dma64_addr_t; +-#if defined(CONFIG_X86_64) || defined(CONFIG_HIGHMEM64G) ++#if defined(CONFIG_X86_64) || defined(CONFIG_XEN) || defined(CONFIG_HIGHMEM64G) + /* DMA addresses come in 32-bit and 64-bit flavours. */ + typedef u64 dma_addr_t; + #else +--- sle11sp1-2010-03-29.orig/arch/x86/vdso/Makefile 2010-03-29 09:00:35.000000000 +0200 ++++ sle11sp1-2010-03-29/arch/x86/vdso/Makefile 2009-12-04 10:44:49.000000000 +0100 +@@ -65,6 +65,8 @@ obj-$(VDSO32-y) += vdso32-syms.lds + vdso32.so-$(VDSO32-y) += int80 + vdso32.so-$(CONFIG_COMPAT) += syscall + vdso32.so-$(VDSO32-y) += sysenter ++xen-vdso32-$(subst 1,$(CONFIG_COMPAT),$(shell expr $(CONFIG_XEN_COMPAT)0 '<' 0x0302000)) += int80 ++vdso32.so-$(CONFIG_XEN) += $(xen-vdso32-y) + + vdso32-images = $(vdso32.so-y:%=vdso32-%.so) + +--- sle11sp1-2010-03-29.orig/arch/x86/vdso/vdso32-setup.c 2010-03-29 09:00:35.000000000 +0200 ++++ sle11sp1-2010-03-29/arch/x86/vdso/vdso32-setup.c 2009-12-04 10:44:46.000000000 +0100 +@@ -26,6 +26,10 @@ + #include + #include + ++#ifdef CONFIG_XEN ++#include ++#endif ++ + enum { + VDSO_DISABLED = 0, + VDSO_ENABLED = 1, +@@ -225,6 +229,7 @@ static inline void map_compat_vdso(int m + + void enable_sep_cpu(void) + { ++#ifndef CONFIG_XEN + int cpu = get_cpu(); + struct tss_struct *tss = &per_cpu(init_tss, cpu); + +@@ -239,6 +244,35 @@ void enable_sep_cpu(void) + wrmsr(MSR_IA32_SYSENTER_ESP, tss->x86_tss.sp1, 0); + wrmsr(MSR_IA32_SYSENTER_EIP, (unsigned long) ia32_sysenter_target, 0); + put_cpu(); ++#else ++ extern asmlinkage void ia32pv_sysenter_target(void); ++ static struct callback_register sysenter = { ++ .type = CALLBACKTYPE_sysenter, ++ .address = { __KERNEL_CS, (unsigned long)ia32pv_sysenter_target }, ++ }; ++ ++ if (!boot_cpu_has(X86_FEATURE_SEP)) ++ return; ++ ++ get_cpu(); ++ ++ if (xen_feature(XENFEAT_supervisor_mode_kernel)) ++ sysenter.address.eip = (unsigned long)ia32_sysenter_target; ++ ++ switch (HYPERVISOR_callback_op(CALLBACKOP_register, &sysenter)) { ++ case 0: ++ break; ++#if CONFIG_XEN_COMPAT < 0x030200 ++ case -ENOSYS: ++ sysenter.type = CALLBACKTYPE_sysenter_deprecated; ++ if (HYPERVISOR_callback_op(CALLBACKOP_register, &sysenter) == 0) ++ break; ++#endif ++ default: ++ clear_bit(X86_FEATURE_SEP, boot_cpu_data.x86_capability); ++ break; ++ } ++#endif + } + + static struct vm_area_struct gate_vma; diff --git a/xen3-auto-arch-x86_64.diff b/xen3-auto-arch-x86_64.diff new file mode 100644 index 0000000..e56489e --- /dev/null +++ b/xen3-auto-arch-x86_64.diff @@ -0,0 +1,211 @@ +Subject: xen3 arch-x86_64 +From: http://xenbits.xensource.com/linux-2.6.18-xen.hg (tip 1011:11175e60d393) +Patch-mainline: obsolete +Acked-by: jbeulich@novell.com + +--- sle11sp1-2010-03-01.orig/arch/x86/kernel/asm-offsets_64.c 2010-03-01 14:09:07.000000000 +0100 ++++ sle11sp1-2010-03-01/arch/x86/kernel/asm-offsets_64.c 2009-12-04 10:44:49.000000000 +0100 +@@ -115,8 +115,10 @@ int main(void) + ENTRY(cr8); + BLANK(); + #undef ENTRY ++#ifndef CONFIG_X86_NO_TSS + DEFINE(TSS_ist, offsetof(struct tss_struct, x86_tss.ist)); + BLANK(); ++#endif + DEFINE(crypto_tfm_ctx_offset, offsetof(struct crypto_tfm, __crt_ctx)); + BLANK(); + DEFINE(__NR_syscall_max, sizeof(syscalls) - 1); +--- sle11sp1-2010-03-01.orig/arch/x86/kernel/machine_kexec_64.c 2009-04-21 10:35:13.000000000 +0200 ++++ sle11sp1-2010-03-01/arch/x86/kernel/machine_kexec_64.c 2009-12-04 10:44:49.000000000 +0100 +@@ -19,6 +19,119 @@ + #include + #include + ++#ifdef CONFIG_XEN ++ ++/* In the case of Xen, override hypervisor functions to be able to create ++ * a regular identity mapping page table... ++ */ ++ ++#include ++#include ++ ++#define x__pmd(x) ((pmd_t) { (x) } ) ++#define x__pud(x) ((pud_t) { (x) } ) ++#define x__pgd(x) ((pgd_t) { (x) } ) ++ ++#define x_pmd_val(x) ((x).pmd) ++#define x_pud_val(x) ((x).pud) ++#define x_pgd_val(x) ((x).pgd) ++ ++static inline void x_set_pmd(pmd_t *dst, pmd_t val) ++{ ++ x_pmd_val(*dst) = x_pmd_val(val); ++} ++ ++static inline void x_set_pud(pud_t *dst, pud_t val) ++{ ++ x_pud_val(*dst) = phys_to_machine(x_pud_val(val)); ++} ++ ++static inline void x_pud_clear (pud_t *pud) ++{ ++ x_pud_val(*pud) = 0; ++} ++ ++static inline void x_set_pgd(pgd_t *dst, pgd_t val) ++{ ++ x_pgd_val(*dst) = phys_to_machine(x_pgd_val(val)); ++} ++ ++static inline void x_pgd_clear (pgd_t * pgd) ++{ ++ x_pgd_val(*pgd) = 0; ++} ++ ++#define X__PAGE_KERNEL_LARGE_EXEC \ ++ _PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_PSE ++#define X_KERNPG_TABLE _PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY ++ ++#define __ma(x) (pfn_to_mfn(__pa((x)) >> PAGE_SHIFT) << PAGE_SHIFT) ++ ++#if PAGES_NR > KEXEC_XEN_NO_PAGES ++#error PAGES_NR is greater than KEXEC_XEN_NO_PAGES - Xen support will break ++#endif ++ ++#if PA_CONTROL_PAGE != 0 ++#error PA_CONTROL_PAGE is non zero - Xen support will break ++#endif ++ ++void machine_kexec_setup_load_arg(xen_kexec_image_t *xki, struct kimage *image) ++{ ++ void *control_page; ++ void *table_page; ++ ++ memset(xki->page_list, 0, sizeof(xki->page_list)); ++ ++ control_page = page_address(image->control_code_page) + PAGE_SIZE; ++ memcpy(control_page, relocate_kernel, PAGE_SIZE); ++ ++ table_page = page_address(image->control_code_page); ++ ++ xki->page_list[PA_CONTROL_PAGE] = __ma(control_page); ++ xki->page_list[PA_TABLE_PAGE] = __ma(table_page); ++ ++ xki->page_list[PA_PGD] = __ma(kexec_pgd); ++ xki->page_list[PA_PUD_0] = __ma(kexec_pud0); ++ xki->page_list[PA_PUD_1] = __ma(kexec_pud1); ++ xki->page_list[PA_PMD_0] = __ma(kexec_pmd0); ++ xki->page_list[PA_PMD_1] = __ma(kexec_pmd1); ++ xki->page_list[PA_PTE_0] = __ma(kexec_pte0); ++ xki->page_list[PA_PTE_1] = __ma(kexec_pte1); ++} ++ ++int __init machine_kexec_setup_resources(struct resource *hypervisor, ++ struct resource *phys_cpus, ++ int nr_phys_cpus) ++{ ++ int k; ++ ++ /* The per-cpu crash note resources belong to the hypervisor resource */ ++ for (k = 0; k < nr_phys_cpus; k++) ++ request_resource(hypervisor, phys_cpus + k); ++ ++ return 0; ++} ++ ++void machine_kexec_register_resources(struct resource *res) { ; } ++ ++#else /* CONFIG_XEN */ ++ ++#define x__pmd(x) __pmd(x) ++#define x__pud(x) __pud(x) ++#define x__pgd(x) __pgd(x) ++ ++#define x_set_pmd(x, y) set_pmd(x, y) ++#define x_set_pud(x, y) set_pud(x, y) ++#define x_set_pgd(x, y) set_pgd(x, y) ++ ++#define x_pud_clear(x) pud_clear(x) ++#define x_pgd_clear(x) pgd_clear(x) ++ ++#define X__PAGE_KERNEL_LARGE_EXEC __PAGE_KERNEL_LARGE_EXEC ++#define X_KERNPG_TABLE _KERNPG_TABLE ++ ++#endif /* CONFIG_XEN */ ++ + static int init_one_level2_page(struct kimage *image, pgd_t *pgd, + unsigned long addr) + { +@@ -61,7 +174,7 @@ static void init_level2_page(pmd_t *leve + addr &= PAGE_MASK; + end_addr = addr + PUD_SIZE; + while (addr < end_addr) { +- set_pmd(level2p++, __pmd(addr | __PAGE_KERNEL_LARGE_EXEC)); ++ x_set_pmd(level2p++, x__pmd(addr | X__PAGE_KERNEL_LARGE_EXEC)); + addr += PMD_SIZE; + } + } +@@ -86,12 +199,12 @@ static int init_level3_page(struct kimag + } + level2p = (pmd_t *)page_address(page); + init_level2_page(level2p, addr); +- set_pud(level3p++, __pud(__pa(level2p) | _KERNPG_TABLE)); ++ x_set_pud(level3p++, x__pud(__pa(level2p) | X_KERNPG_TABLE)); + addr += PUD_SIZE; + } + /* clear the unused entries */ + while (addr < end_addr) { +- pud_clear(level3p++); ++ x_pud_clear(level3p++); + addr += PUD_SIZE; + } + out: +@@ -121,12 +234,12 @@ static int init_level4_page(struct kimag + result = init_level3_page(image, level3p, addr, last_addr); + if (result) + goto out; +- set_pgd(level4p++, __pgd(__pa(level3p) | _KERNPG_TABLE)); ++ x_set_pgd(level4p++, x__pgd(__pa(level3p) | X_KERNPG_TABLE)); + addr += PGDIR_SIZE; + } + /* clear the unused entries */ + while (addr < end_addr) { +- pgd_clear(level4p++); ++ x_pgd_clear(level4p++); + addr += PGDIR_SIZE; + } + out: +@@ -187,8 +300,14 @@ static int init_pgtable(struct kimage *i + { + pgd_t *level4p; + int result; ++ unsigned long x_max_pfn = max_pfn; ++ ++#ifdef CONFIG_XEN ++ x_max_pfn = HYPERVISOR_memory_op(XENMEM_maximum_ram_page, NULL); ++#endif ++ + level4p = (pgd_t *)__va(start_pgtable); +- result = init_level4_page(image, level4p, 0, max_pfn << PAGE_SHIFT); ++ result = init_level4_page(image, level4p, 0, x_max_pfn << PAGE_SHIFT); + if (result) + return result; + /* +@@ -222,6 +341,7 @@ void machine_kexec_cleanup(struct kimage + free_transition_pgtable(image); + } + ++#ifndef CONFIG_XEN + /* + * Do not allocate memory (or fail in any way) in machine_kexec(). + * We are past the point of no return, committed to rebooting now. +@@ -280,6 +400,7 @@ void machine_kexec(struct kimage *image) + + __ftrace_enabled_restore(save_ftrace_enabled); + } ++#endif + + void arch_crash_save_vmcoreinfo(void) + { diff --git a/xen3-auto-common.diff b/xen3-auto-common.diff new file mode 100644 index 0000000..9f069f2 --- /dev/null +++ b/xen3-auto-common.diff @@ -0,0 +1,4158 @@ +Subject: xen3 common +From: http://xenbits.xensource.com/linux-2.6.18-xen.hg (tip 1011:11175e60d393) +Patch-mainline: obsolete +Acked-by: jbeulich@novell.com + +List of files that don't require modification anymore (and hence +removed from this patch), for reference and in case upstream wants to +take the forward porting patches: +2.6.22/include/linux/sched.h +2.6.22/kernel/softlockup.c +2.6.22/kernel/timer.c +2.6.25/mm/highmem.c +2.6.30/include/linux/pci_regs.h + +--- sle11sp1-2010-03-22.orig/drivers/Makefile 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/Makefile 2009-12-04 10:44:41.000000000 +0100 +@@ -33,6 +33,7 @@ obj-$(CONFIG_PARPORT) += parport/ + obj-y += base/ block/ misc/ mfd/ + obj-$(CONFIG_NUBUS) += nubus/ + obj-y += macintosh/ ++obj-$(CONFIG_XEN) += xen/ + obj-$(CONFIG_SCSI) += scsi/ + obj-$(CONFIG_ATA) += ata/ + obj-$(CONFIG_MTD) += mtd/ +--- sle11sp1-2010-03-22.orig/drivers/acpi/Makefile 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/acpi/Makefile 2009-12-04 10:44:41.000000000 +0100 +@@ -62,5 +62,8 @@ obj-$(CONFIG_ACPI_POWER_METER) += power_ + processor-y := processor_core.o processor_throttling.o + processor-y += processor_idle.o processor_thermal.o + processor-$(CONFIG_CPU_FREQ) += processor_perflib.o ++ifdef CONFIG_PROCESSOR_EXTERNAL_CONTROL ++processor-objs += processor_perflib.o processor_extcntl.o ++endif + + obj-$(CONFIG_ACPI_PROCESSOR_AGGREGATOR) += acpi_pad.o +--- sle11sp1-2010-03-22.orig/drivers/acpi/acpica/hwsleep.c 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/acpi/acpica/hwsleep.c 2009-12-04 10:44:41.000000000 +0100 +@@ -236,7 +236,11 @@ acpi_status asmlinkage acpi_enter_sleep_ + u32 pm1b_control; + struct acpi_bit_register_info *sleep_type_reg_info; + struct acpi_bit_register_info *sleep_enable_reg_info; ++#if !(defined(CONFIG_XEN) && defined(CONFIG_X86)) + u32 in_value; ++#else ++ int err; ++#endif + struct acpi_object_list arg_list; + union acpi_object arg; + acpi_status status; +@@ -347,6 +351,7 @@ acpi_status asmlinkage acpi_enter_sleep_ + + /* Write #2: Write both SLP_TYP + SLP_EN */ + ++#if !(defined(CONFIG_XEN) && defined(CONFIG_X86)) + status = acpi_hw_write_pm1_control(pm1a_control, pm1b_control); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); +@@ -386,6 +391,16 @@ acpi_status asmlinkage acpi_enter_sleep_ + /* Spin until we wake */ + + } while (!in_value); ++#else ++ /* PV ACPI just need check hypercall return value */ ++ err = acpi_notify_hypervisor_state(sleep_state, ++ PM1Acontrol, PM1Bcontrol); ++ if (err) { ++ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, ++ "Hypervisor failure [%d]\n", err)); ++ return_ACPI_STATUS(AE_ERROR); ++ } ++#endif + + return_ACPI_STATUS(AE_OK); + } +--- sle11sp1-2010-03-22.orig/drivers/acpi/processor_core.c 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/acpi/processor_core.c 2009-12-07 10:38:01.000000000 +0100 +@@ -660,7 +660,8 @@ static int acpi_processor_get_info(struc + */ + if (pr->id == -1) { + if (ACPI_FAILURE +- (acpi_processor_hotadd_init(pr->handle, &pr->id))) { ++ (acpi_processor_hotadd_init(pr->handle, &pr->id)) && ++ !processor_cntl_external()) { + return -ENODEV; + } + } +@@ -711,7 +712,11 @@ static int acpi_processor_get_info(struc + return 0; + } + ++#ifndef CONFIG_XEN + static DEFINE_PER_CPU(void *, processor_device_array); ++#else ++static void *processor_device_array[NR_ACPI_CPUS]; ++#endif + + static void acpi_processor_notify(struct acpi_device *device, u32 event) + { +@@ -792,29 +797,45 @@ static int __cpuinit acpi_processor_add( + strcpy(acpi_device_class(device), ACPI_PROCESSOR_CLASS); + device->driver_data = pr; + ++ processor_extcntl_init(); ++ + result = acpi_processor_get_info(device); +- if (result) { ++ if (result || ++ ((pr->id == -1) && !processor_cntl_external())) { + /* Processor is physically not present */ + return 0; + } + +- BUG_ON((pr->id >= nr_cpu_ids) || (pr->id < 0)); ++ BUG_ON(!processor_cntl_external() && ++ ((pr->id >= nr_cpu_ids) || (pr->id < 0))); + + /* + * Buggy BIOS check + * ACPI id of processors can be reported wrongly by the BIOS. + * Don't trust it blindly + */ ++#ifndef CONFIG_XEN + if (per_cpu(processor_device_array, pr->id) != NULL && + per_cpu(processor_device_array, pr->id) != device) { ++#else ++ BUG_ON(pr->acpi_id >= NR_ACPI_CPUS); ++ if (processor_device_array[pr->acpi_id] != NULL && ++ processor_device_array[pr->acpi_id] != device) { ++#endif + printk(KERN_WARNING "BIOS reported wrong ACPI id " + "for the processor\n"); + result = -ENODEV; + goto err_free_cpumask; + } ++#ifndef CONFIG_XEN + per_cpu(processor_device_array, pr->id) = device; + + per_cpu(processors, pr->id) = pr; ++#else ++ processor_device_array[pr->acpi_id] = device; ++ if (pr->id != -1) ++ per_cpu(processors, pr->id) = pr; ++#endif + + result = acpi_processor_add_fs(device); + if (result) +@@ -831,15 +852,27 @@ static int __cpuinit acpi_processor_add( + acpi_processor_set_pdc(pr); + arch_acpi_processor_cleanup_pdc(pr); + +-#ifdef CONFIG_CPU_FREQ ++#if defined(CONFIG_CPU_FREQ) || defined(CONFIG_PROCESSOR_EXTERNAL_CONTROL) + acpi_processor_ppc_has_changed(pr); + #endif +- acpi_processor_get_throttling_info(pr); +- acpi_processor_get_limit_info(pr); + ++ /* ++ * pr->id may equal to -1 while processor_cntl_external enabled. ++ * throttle and thermal module don't support this case. ++ * Tx only works when dom0 vcpu == pcpu num by far, as we give ++ * control to dom0. ++ */ ++ if (pr->id != -1) { ++ acpi_processor_get_throttling_info(pr); ++ acpi_processor_get_limit_info(pr); ++ } + + acpi_processor_power_init(pr, device); + ++ result = processor_extcntl_prepare(pr); ++ if (result) ++ goto end; ++ + pr->cdev = thermal_cooling_device_register("Processor", device, + &processor_cooling_ops); + if (IS_ERR(pr->cdev)) { +@@ -891,7 +924,7 @@ static int acpi_processor_remove(struct + + pr = acpi_driver_data(device); + +- if (pr->id >= nr_cpu_ids) ++ if (!processor_cntl_external() && pr->id >= nr_cpu_ids) + goto free; + + if (type == ACPI_BUS_REMOVAL_EJECT) { +@@ -912,8 +945,14 @@ static int acpi_processor_remove(struct + pr->cdev = NULL; + } + ++#ifndef CONFIG_XEN + per_cpu(processors, pr->id) = NULL; + per_cpu(processor_device_array, pr->id) = NULL; ++#else ++ if (pr->id != -1) ++ per_cpu(processors, pr->id) = NULL; ++ processor_device_array[pr->acpi_id] = NULL; ++#endif + + free: + free_cpumask_var(pr->throttling.shared_cpu_map); +@@ -969,6 +1008,10 @@ int acpi_processor_device_add(acpi_handl + return -ENODEV; + } + ++ if (processor_cntl_external() && acpi_driver_data(*device)) ++ processor_notify_external(acpi_driver_data(*device), ++ PROCESSOR_HOTPLUG, HOTPLUG_TYPE_ADD); ++ + return 0; + } + +@@ -998,6 +1041,10 @@ static void __ref acpi_processor_hotplug + "Unable to add the device\n"); + break; + } ++ pr = acpi_driver_data(device); ++ if (processor_cntl_external() && pr) ++ processor_notify_external(pr, ++ PROCESSOR_HOTPLUG, HOTPLUG_TYPE_ADD); + break; + case ACPI_NOTIFY_EJECT_REQUEST: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, +@@ -1014,6 +1061,9 @@ static void __ref acpi_processor_hotplug + "Driver data is NULL, dropping EJECT\n"); + return; + } ++ if (processor_cntl_external()) ++ processor_notify_external(pr, PROCESSOR_HOTPLUG, ++ HOTPLUG_TYPE_REMOVE); + break; + default: + ACPI_DEBUG_PRINT((ACPI_DB_INFO, +@@ -1078,6 +1128,11 @@ static acpi_status acpi_processor_hotadd + + static int acpi_processor_handle_eject(struct acpi_processor *pr) + { ++#ifdef CONFIG_XEN ++ if (pr->id == -1) ++ return (0); ++#endif ++ + if (cpu_online(pr->id)) + cpu_down(pr->id); + +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/drivers/acpi/processor_extcntl.c 2009-12-04 10:44:41.000000000 +0100 +@@ -0,0 +1,241 @@ ++/* ++ * processor_extcntl.c - channel to external control logic ++ * ++ * Copyright (C) 2008, Intel corporation ++ * ++ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or (at ++ * your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#define ACPI_PROCESSOR_COMPONENT 0x01000000 ++#define ACPI_PROCESSOR_CLASS "processor" ++#define ACPI_PROCESSOR_DRIVER_NAME "ACPI Processor Driver" ++#define _COMPONENT ACPI_PROCESSOR_COMPONENT ++ACPI_MODULE_NAME("acpi_processor") ++ ++static int processor_extcntl_parse_csd(struct acpi_processor *pr); ++static int processor_extcntl_get_performance(struct acpi_processor *pr); ++/* ++ * External processor control logic may register with its own set of ++ * ops to get ACPI related notification. One example is like VMM. ++ */ ++const struct processor_extcntl_ops *processor_extcntl_ops; ++EXPORT_SYMBOL(processor_extcntl_ops); ++ ++static int processor_notify_smm(void) ++{ ++ acpi_status status; ++ static int is_done = 0; ++ ++ /* only need successfully notify BIOS once */ ++ /* avoid double notification which may lead to unexpected result */ ++ if (is_done) ++ return 0; ++ ++ /* Can't write pstate_cnt to smi_cmd if either value is zero */ ++ if ((!acpi_fadt.smi_cmd) || (!acpi_fadt.pstate_cnt)) { ++ ACPI_DEBUG_PRINT((ACPI_DB_INFO,"No SMI port or pstate_cnt\n")); ++ return 0; ++ } ++ ++ ACPI_DEBUG_PRINT((ACPI_DB_INFO, ++ "Writing pstate_cnt [0x%x] to smi_cmd [0x%x]\n", ++ acpi_fadt.pstate_cnt, acpi_fadt.smi_cmd)); ++ ++ /* FADT v1 doesn't support pstate_cnt, many BIOS vendors use ++ * it anyway, so we need to support it... */ ++ if (acpi_fadt_is_v1) { ++ ACPI_DEBUG_PRINT((ACPI_DB_INFO, ++ "Using v1.0 FADT reserved value for pstate_cnt\n")); ++ } ++ ++ status = acpi_os_write_port(acpi_fadt.smi_cmd, ++ (u32) acpi_fadt.pstate_cnt, 8); ++ if (ACPI_FAILURE(status)) ++ return status; ++ ++ is_done = 1; ++ ++ return 0; ++} ++ ++int processor_notify_external(struct acpi_processor *pr, int event, int type) ++{ ++ int ret = -EINVAL; ++ ++ if (!processor_cntl_external()) ++ return -EINVAL; ++ ++ switch (event) { ++ case PROCESSOR_PM_INIT: ++ case PROCESSOR_PM_CHANGE: ++ if ((type >= PM_TYPE_MAX) || ++ !processor_extcntl_ops->pm_ops[type]) ++ break; ++ ++ ret = processor_extcntl_ops->pm_ops[type](pr, event); ++ break; ++ case PROCESSOR_HOTPLUG: ++ if (processor_extcntl_ops->hotplug) ++ ret = processor_extcntl_ops->hotplug(pr, type); ++ break; ++ default: ++ printk(KERN_ERR "Unsupport processor events %d.\n", event); ++ break; ++ } ++ ++ return ret; ++} ++ ++/* ++ * External control logic can decide to grab full or part of physical ++ * processor control bits. Take a VMM for example, physical processors ++ * are owned by VMM and thus existence information like hotplug is ++ * always required to be notified to VMM. Similar is processor idle ++ * state which is also necessarily controlled by VMM. But for other ++ * control bits like performance/throttle states, VMM may choose to ++ * control or not upon its own policy. ++ */ ++void processor_extcntl_init(void) ++{ ++ if (!processor_extcntl_ops) ++ arch_acpi_processor_init_extcntl(&processor_extcntl_ops); ++} ++ ++/* ++ * This is called from ACPI processor init, and targeted to hold ++ * some tricky housekeeping jobs to satisfy external control model. ++ * For example, we may put dependency parse stub here for idle ++ * and performance state. Those information may be not available ++ * if splitting from dom0 control logic like cpufreq driver. ++ */ ++int processor_extcntl_prepare(struct acpi_processor *pr) ++{ ++ /* parse cstate dependency information */ ++ if (processor_pm_external()) ++ processor_extcntl_parse_csd(pr); ++ ++ /* Initialize performance states */ ++ if (processor_pmperf_external()) ++ processor_extcntl_get_performance(pr); ++ ++ return 0; ++} ++ ++/* ++ * Currently no _CSD is implemented which is why existing ACPI code ++ * doesn't parse _CSD at all. But to keep interface complete with ++ * external control logic, we put a placeholder here for future ++ * compatibility. ++ */ ++static int processor_extcntl_parse_csd(struct acpi_processor *pr) ++{ ++ int i; ++ ++ for (i = 0; i < pr->power.count; i++) { ++ if (!pr->power.states[i].valid) ++ continue; ++ ++ /* No dependency by default */ ++ pr->power.states[i].domain_info = NULL; ++ pr->power.states[i].csd_count = 0; ++ } ++ ++ return 0; ++} ++ ++/* ++ * Existing ACPI module does parse performance states at some point, ++ * when acpi-cpufreq driver is loaded which however is something ++ * we'd like to disable to avoid confliction with external control ++ * logic. So we have to collect raw performance information here ++ * when ACPI processor object is found and started. ++ */ ++static int processor_extcntl_get_performance(struct acpi_processor *pr) ++{ ++ int ret; ++ struct acpi_processor_performance *perf; ++ struct acpi_psd_package *pdomain; ++ ++ if (pr->performance) ++ return -EBUSY; ++ ++ perf = kzalloc(sizeof(struct acpi_processor_performance), GFP_KERNEL); ++ if (!perf) ++ return -ENOMEM; ++ ++ pr->performance = perf; ++ /* Get basic performance state information */ ++ ret = acpi_processor_get_performance_info(pr); ++ if (ret < 0) ++ goto err_out; ++ ++ /* ++ * Well, here we need retrieve performance dependency information ++ * from _PSD object. The reason why existing interface is not used ++ * is due to the reason that existing interface sticks to Linux cpu ++ * id to construct some bitmap, however we want to split ACPI ++ * processor objects from Linux cpu id logic. For example, even ++ * when Linux is configured as UP, we still want to parse all ACPI ++ * processor objects to external logic. In this case, it's preferred ++ * to use ACPI ID instead. ++ */ ++ pdomain = &pr->performance->domain_info; ++ pdomain->num_processors = 0; ++ ret = acpi_processor_get_psd(pr); ++ if (ret < 0) { ++ /* ++ * _PSD is optional - assume no coordination if absent (or ++ * broken), matching native kernels' behavior. ++ */ ++ pdomain->num_entries = ACPI_PSD_REV0_ENTRIES; ++ pdomain->revision = ACPI_PSD_REV0_REVISION; ++ pdomain->domain = pr->acpi_id; ++ pdomain->coord_type = DOMAIN_COORD_TYPE_SW_ALL; ++ pdomain->num_processors = 1; ++ } ++ ++ /* Some sanity check */ ++ if ((pdomain->revision != ACPI_PSD_REV0_REVISION) || ++ (pdomain->num_entries != ACPI_PSD_REV0_ENTRIES) || ++ ((pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ALL) && ++ (pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ANY) && ++ (pdomain->coord_type != DOMAIN_COORD_TYPE_HW_ALL))) { ++ ret = -EINVAL; ++ goto err_out; ++ } ++ ++ /* Last step is to notify BIOS that external logic exists */ ++ processor_notify_smm(); ++ ++ processor_notify_external(pr, PROCESSOR_PM_INIT, PM_TYPE_PERF); ++ ++ return 0; ++err_out: ++ pr->performance = NULL; ++ kfree(perf); ++ return ret; ++} +--- sle11sp1-2010-03-22.orig/drivers/acpi/processor_idle.c 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/acpi/processor_idle.c 2010-03-01 14:17:02.000000000 +0100 +@@ -449,7 +449,8 @@ static int acpi_processor_get_power_info + */ + cx.entry_method = ACPI_CSTATE_HALT; + snprintf(cx.desc, ACPI_CX_DESC_LEN, "ACPI HLT"); +- } else { ++ /* This doesn't apply to external control case */ ++ } else if (!processor_pm_external()) { + continue; + } + if (cx.type == ACPI_STATE_C1 && +@@ -488,6 +489,12 @@ static int acpi_processor_get_power_info + + cx.power = obj->integer.value; + ++#ifdef CONFIG_PROCESSOR_EXTERNAL_CONTROL ++ /* cache control methods to notify external logic */ ++ if (processor_pm_external()) ++ memcpy(&cx.reg, reg, sizeof(*reg)); ++#endif ++ + current_count++; + memcpy(&(pr->power.states[current_count]), &cx, sizeof(cx)); + +@@ -1237,6 +1244,11 @@ int __cpuinit acpi_processor_power_init( + if (!entry) + return -EIO; + #endif ++ ++ if (processor_pm_external()) ++ processor_notify_external(pr, ++ PROCESSOR_PM_INIT, PM_TYPE_IDLE); ++ + return 0; + } + +--- sle11sp1-2010-03-22.orig/drivers/acpi/processor_perflib.c 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/acpi/processor_perflib.c 2010-03-22 12:14:02.000000000 +0100 +@@ -78,6 +78,7 @@ MODULE_PARM_DESC(ignore_ppc, "If the fre + + static int acpi_processor_ppc_status; + ++#ifdef CONFIG_CPU_FREQ + static int acpi_processor_ppc_notifier(struct notifier_block *nb, + unsigned long event, void *data) + { +@@ -120,6 +121,7 @@ static int acpi_processor_ppc_notifier(s + static struct notifier_block acpi_ppc_notifier_block = { + .notifier_call = acpi_processor_ppc_notifier, + }; ++#endif /* CONFIG_CPU_FREQ */ + + static int acpi_processor_get_platform_limit(struct acpi_processor *pr) + { +@@ -164,9 +166,15 @@ int acpi_processor_ppc_has_changed(struc + if (ret < 0) + return (ret); + else ++#ifdef CONFIG_CPU_FREQ + return cpufreq_update_policy(pr->id); ++#elif defined(CONFIG_PROCESSOR_EXTERNAL_CONTROL) ++ return processor_notify_external(pr, ++ PROCESSOR_PM_CHANGE, PM_TYPE_PERF); ++#endif + } + ++#ifdef CONFIG_CPU_FREQ + void acpi_processor_ppc_init(void) + { + if (!cpufreq_register_notifier +@@ -185,6 +193,7 @@ void acpi_processor_ppc_exit(void) + + acpi_processor_ppc_status &= ~PPC_REGISTERED; + } ++#endif /* CONFIG_CPU_FREQ */ + + static int acpi_processor_get_performance_control(struct acpi_processor *pr) + { +@@ -332,7 +341,10 @@ static int acpi_processor_get_performanc + return result; + } + +-static int acpi_processor_get_performance_info(struct acpi_processor *pr) ++#ifndef CONFIG_PROCESSOR_EXTERNAL_CONTROL ++static ++#endif ++int acpi_processor_get_performance_info(struct acpi_processor *pr) + { + int result = 0; + acpi_status status = AE_OK; +@@ -377,6 +389,7 @@ static int acpi_processor_get_performanc + return result; + } + ++#ifdef CONFIG_CPU_FREQ + int acpi_processor_notify_smm(struct module *calling_module) + { + acpi_status status; +@@ -437,8 +450,12 @@ int acpi_processor_notify_smm(struct mod + } + + EXPORT_SYMBOL(acpi_processor_notify_smm); ++#endif /* CONFIG_CPU_FREQ */ + +-static int acpi_processor_get_psd(struct acpi_processor *pr) ++#ifndef CONFIG_PROCESSOR_EXTERNAL_CONTROL ++static ++#endif ++int acpi_processor_get_psd(struct acpi_processor *pr) + { + int result = 0; + acpi_status status = AE_OK; +--- sle11sp1-2010-03-22.orig/drivers/acpi/sleep.c 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/acpi/sleep.c 2009-12-04 10:44:41.000000000 +0100 +@@ -60,6 +60,7 @@ static struct notifier_block tts_notifie + static int acpi_sleep_prepare(u32 acpi_state) + { + #ifdef CONFIG_ACPI_SLEEP ++#ifndef CONFIG_ACPI_PV_SLEEP + /* do we have a wakeup address for S2 and S3? */ + if (acpi_state == ACPI_STATE_S3) { + if (!acpi_wakeup_address) { +@@ -69,6 +70,7 @@ static int acpi_sleep_prepare(u32 acpi_s + (acpi_physical_address)acpi_wakeup_address); + + } ++#endif + ACPI_FLUSH_CPU_CACHE(); + acpi_enable_wakeup_device_prep(acpi_state); + #endif +@@ -244,7 +246,14 @@ static int acpi_suspend_enter(suspend_st + break; + + case ACPI_STATE_S3: ++#ifdef CONFIG_ACPI_PV_SLEEP ++ /* Hyperviosr will save and restore CPU context ++ * and then we can skip low level housekeeping here. ++ */ ++ acpi_enter_sleep_state(acpi_state); ++#else + do_suspend_lowlevel(); ++#endif + break; + } + +--- sle11sp1-2010-03-22.orig/drivers/char/agp/intel-agp.c 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/char/agp/intel-agp.c 2010-01-20 10:22:01.000000000 +0100 +@@ -400,6 +400,13 @@ static struct page *i8xx_alloc_pages(voi + if (page == NULL) + return NULL; + ++#ifdef CONFIG_XEN ++ if (xen_create_contiguous_region((unsigned long)page_address(page), 2, 32)) { ++ __free_pages(page, 2); ++ return NULL; ++ } ++#endif ++ + if (set_pages_uc(page, 4) < 0) { + set_pages_wb(page, 4); + __free_pages(page, 2); +@@ -416,6 +423,9 @@ static void i8xx_destroy_pages(struct pa + return; + + set_pages_wb(page, 4); ++#ifdef CONFIG_XEN ++ xen_destroy_contiguous_region((unsigned long)page_address(page), 2); ++#endif + put_page(page); + __free_pages(page, 2); + atomic_dec(&agp_bridge->current_memory_agp); +--- sle11sp1-2010-03-22.orig/drivers/char/mem.c 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/char/mem.c 2010-03-01 14:17:07.000000000 +0100 +@@ -123,6 +123,7 @@ void __attribute__((weak)) unxlate_dev_m + { + } + ++#ifndef ARCH_HAS_DEV_MEM + /* + * This funcion reads the *physical* memory. The f_pos points directly to the + * memory location. +@@ -267,6 +268,7 @@ static ssize_t write_mem(struct file * f + *ppos += written; + return written; + } ++#endif + + int __attribute__((weak)) phys_mem_access_prot_allowed(struct file *file, + unsigned long pfn, unsigned long size, pgprot_t *vma_prot) +@@ -358,6 +360,9 @@ static int mmap_mem(struct file * file, + static int mmap_kmem(struct file * file, struct vm_area_struct * vma) + { + unsigned long pfn; ++#ifdef CONFIG_XEN ++ unsigned long i, count; ++#endif + + /* Turn a kernel-virtual address into a physical page frame */ + pfn = __pa((u64)vma->vm_pgoff << PAGE_SHIFT) >> PAGE_SHIFT; +@@ -372,6 +377,13 @@ static int mmap_kmem(struct file * file, + if (!pfn_valid(pfn)) + return -EIO; + ++#ifdef CONFIG_XEN ++ count = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; ++ for (i = 0; i < count; i++) ++ if ((pfn + i) != mfn_to_local_pfn(pfn_to_mfn(pfn + i))) ++ return -EIO; ++#endif ++ + vma->vm_pgoff = pfn; + return mmap_mem(file, vma); + } +@@ -879,6 +891,7 @@ static int open_port(struct inode * inod + #define open_kmem open_mem + #define open_oldmem open_mem + ++#ifndef ARCH_HAS_DEV_MEM + static const struct file_operations mem_fops = { + .llseek = memory_lseek, + .read = read_mem, +@@ -887,6 +900,9 @@ static const struct file_operations mem_ + .open = open_mem, + .get_unmapped_area = get_unmapped_area_mem, + }; ++#else ++extern const struct file_operations mem_fops; ++#endif + + #ifdef CONFIG_DEVKMEM + static const struct file_operations kmem_fops = { +--- sle11sp1-2010-03-22.orig/drivers/char/tpm/Makefile 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/char/tpm/Makefile 2009-12-04 10:44:41.000000000 +0100 +@@ -9,3 +9,5 @@ obj-$(CONFIG_TCG_TIS) += tpm_tis.o + obj-$(CONFIG_TCG_NSC) += tpm_nsc.o + obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o + obj-$(CONFIG_TCG_INFINEON) += tpm_infineon.o ++obj-$(CONFIG_TCG_XEN) += tpm_xenu.o ++tpm_xenu-y = tpm_xen.o tpm_vtpm.o +--- sle11sp1-2010-03-22.orig/drivers/char/tpm/tpm.h 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/char/tpm/tpm.h 2009-12-04 10:44:41.000000000 +0100 +@@ -108,6 +108,9 @@ struct tpm_chip { + struct dentry **bios_dir; + + struct list_head list; ++#ifdef CONFIG_XEN ++ void *priv; ++#endif + void (*release) (struct device *); + }; + +@@ -266,6 +269,18 @@ struct tpm_cmd_t { + + ssize_t tpm_getcap(struct device *, __be32, cap_t *, const char *); + ++#ifdef CONFIG_XEN ++static inline void *chip_get_private(const struct tpm_chip *chip) ++{ ++ return chip->priv; ++} ++ ++static inline void chip_set_private(struct tpm_chip *chip, void *priv) ++{ ++ chip->priv = priv; ++} ++#endif ++ + extern void tpm_get_timeouts(struct tpm_chip *); + extern void tpm_gen_interrupt(struct tpm_chip *); + extern void tpm_continue_selftest(struct tpm_chip *); +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/drivers/char/tpm/tpm_vtpm.c 2009-12-04 10:44:41.000000000 +0100 +@@ -0,0 +1,542 @@ ++/* ++ * Copyright (C) 2006 IBM Corporation ++ * ++ * Authors: ++ * Stefan Berger ++ * ++ * Generic device driver part for device drivers in a virtualized ++ * environment. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation, version 2 of the ++ * License. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include "tpm.h" ++#include "tpm_vtpm.h" ++ ++/* read status bits */ ++enum { ++ STATUS_BUSY = 0x01, ++ STATUS_DATA_AVAIL = 0x02, ++ STATUS_READY = 0x04 ++}; ++ ++struct transmission { ++ struct list_head next; ++ ++ unsigned char *request; ++ size_t request_len; ++ size_t request_buflen; ++ ++ unsigned char *response; ++ size_t response_len; ++ size_t response_buflen; ++ ++ unsigned int flags; ++}; ++ ++enum { ++ TRANSMISSION_FLAG_WAS_QUEUED = 0x1 ++}; ++ ++ ++enum { ++ DATAEX_FLAG_QUEUED_ONLY = 0x1 ++}; ++ ++ ++/* local variables */ ++ ++/* local function prototypes */ ++static int _vtpm_send_queued(struct tpm_chip *chip); ++ ++ ++/* ============================================================= ++ * Some utility functions ++ * ============================================================= ++ */ ++static void vtpm_state_init(struct vtpm_state *vtpms) ++{ ++ vtpms->current_request = NULL; ++ spin_lock_init(&vtpms->req_list_lock); ++ init_waitqueue_head(&vtpms->req_wait_queue); ++ INIT_LIST_HEAD(&vtpms->queued_requests); ++ ++ vtpms->current_response = NULL; ++ spin_lock_init(&vtpms->resp_list_lock); ++ init_waitqueue_head(&vtpms->resp_wait_queue); ++ ++ vtpms->disconnect_time = jiffies; ++} ++ ++ ++static inline struct transmission *transmission_alloc(void) ++{ ++ return kzalloc(sizeof(struct transmission), GFP_ATOMIC); ++} ++ ++static unsigned char * ++transmission_set_req_buffer(struct transmission *t, ++ unsigned char *buffer, size_t len) ++{ ++ if (t->request_buflen < len) { ++ kfree(t->request); ++ t->request = kmalloc(len, GFP_KERNEL); ++ if (!t->request) { ++ t->request_buflen = 0; ++ return NULL; ++ } ++ t->request_buflen = len; ++ } ++ ++ memcpy(t->request, buffer, len); ++ t->request_len = len; ++ ++ return t->request; ++} ++ ++static unsigned char * ++transmission_set_res_buffer(struct transmission *t, ++ const unsigned char *buffer, size_t len) ++{ ++ if (t->response_buflen < len) { ++ kfree(t->response); ++ t->response = kmalloc(len, GFP_ATOMIC); ++ if (!t->response) { ++ t->response_buflen = 0; ++ return NULL; ++ } ++ t->response_buflen = len; ++ } ++ ++ memcpy(t->response, buffer, len); ++ t->response_len = len; ++ ++ return t->response; ++} ++ ++static inline void transmission_free(struct transmission *t) ++{ ++ kfree(t->request); ++ kfree(t->response); ++ kfree(t); ++} ++ ++/* ============================================================= ++ * Interface with the lower layer driver ++ * ============================================================= ++ */ ++/* ++ * Lower layer uses this function to make a response available. ++ */ ++int vtpm_vd_recv(const struct tpm_chip *chip, ++ const unsigned char *buffer, size_t count, ++ void *ptr) ++{ ++ unsigned long flags; ++ int ret_size = 0; ++ struct transmission *t; ++ struct vtpm_state *vtpms; ++ ++ vtpms = (struct vtpm_state *)chip_get_private(chip); ++ ++ /* ++ * The list with requests must contain one request ++ * only and the element there must be the one that ++ * was passed to me from the front-end. ++ */ ++ spin_lock_irqsave(&vtpms->resp_list_lock, flags); ++ if (vtpms->current_request != ptr) { ++ spin_unlock_irqrestore(&vtpms->resp_list_lock, flags); ++ return 0; ++ } ++ ++ if ((t = vtpms->current_request)) { ++ transmission_free(t); ++ vtpms->current_request = NULL; ++ } ++ ++ t = transmission_alloc(); ++ if (t) { ++ if (!transmission_set_res_buffer(t, buffer, count)) { ++ transmission_free(t); ++ spin_unlock_irqrestore(&vtpms->resp_list_lock, flags); ++ return -ENOMEM; ++ } ++ ret_size = count; ++ vtpms->current_response = t; ++ wake_up_interruptible(&vtpms->resp_wait_queue); ++ } ++ spin_unlock_irqrestore(&vtpms->resp_list_lock, flags); ++ ++ return ret_size; ++} ++ ++ ++/* ++ * Lower layer indicates its status (connected/disconnected) ++ */ ++void vtpm_vd_status(const struct tpm_chip *chip, u8 vd_status) ++{ ++ struct vtpm_state *vtpms; ++ ++ vtpms = (struct vtpm_state *)chip_get_private(chip); ++ ++ vtpms->vd_status = vd_status; ++ if ((vtpms->vd_status & TPM_VD_STATUS_CONNECTED) == 0) { ++ vtpms->disconnect_time = jiffies; ++ } ++} ++ ++/* ============================================================= ++ * Interface with the generic TPM driver ++ * ============================================================= ++ */ ++static int vtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count) ++{ ++ int rc = 0; ++ unsigned long flags; ++ struct vtpm_state *vtpms; ++ ++ vtpms = (struct vtpm_state *)chip_get_private(chip); ++ ++ /* ++ * Check if the previous operation only queued the command ++ * In this case there won't be a response, so I just ++ * return from here and reset that flag. In any other ++ * case I should receive a response from the back-end. ++ */ ++ spin_lock_irqsave(&vtpms->resp_list_lock, flags); ++ if ((vtpms->flags & DATAEX_FLAG_QUEUED_ONLY) != 0) { ++ vtpms->flags &= ~DATAEX_FLAG_QUEUED_ONLY; ++ spin_unlock_irqrestore(&vtpms->resp_list_lock, flags); ++ /* ++ * The first few commands (measurements) must be ++ * queued since it might not be possible to talk to the ++ * TPM, yet. ++ * Return a response of up to 30 '0's. ++ */ ++ ++ count = min_t(size_t, count, 30); ++ memset(buf, 0x0, count); ++ return count; ++ } ++ /* ++ * Check whether something is in the responselist and if ++ * there's nothing in the list wait for something to appear. ++ */ ++ ++ if (!vtpms->current_response) { ++ spin_unlock_irqrestore(&vtpms->resp_list_lock, flags); ++ interruptible_sleep_on_timeout(&vtpms->resp_wait_queue, ++ 1000); ++ spin_lock_irqsave(&vtpms->resp_list_lock ,flags); ++ } ++ ++ if (vtpms->current_response) { ++ struct transmission *t = vtpms->current_response; ++ vtpms->current_response = NULL; ++ rc = min(count, t->response_len); ++ memcpy(buf, t->response, rc); ++ transmission_free(t); ++ } ++ ++ spin_unlock_irqrestore(&vtpms->resp_list_lock, flags); ++ return rc; ++} ++ ++static int vtpm_send(struct tpm_chip *chip, u8 *buf, size_t count) ++{ ++ int rc = 0; ++ unsigned long flags; ++ struct transmission *t = transmission_alloc(); ++ struct vtpm_state *vtpms; ++ ++ vtpms = (struct vtpm_state *)chip_get_private(chip); ++ ++ if (!t) ++ return -ENOMEM; ++ /* ++ * If there's a current request, it must be the ++ * previous request that has timed out. ++ */ ++ spin_lock_irqsave(&vtpms->req_list_lock, flags); ++ if (vtpms->current_request != NULL) { ++ printk("WARNING: Sending although there is a request outstanding.\n" ++ " Previous request must have timed out.\n"); ++ transmission_free(vtpms->current_request); ++ vtpms->current_request = NULL; ++ } ++ spin_unlock_irqrestore(&vtpms->req_list_lock, flags); ++ ++ /* ++ * Queue the packet if the driver below is not ++ * ready, yet, or there is any packet already ++ * in the queue. ++ * If the driver below is ready, unqueue all ++ * packets first before sending our current ++ * packet. ++ * For each unqueued packet, except for the ++ * last (=current) packet, call the function ++ * tpm_xen_recv to wait for the response to come ++ * back. ++ */ ++ if ((vtpms->vd_status & TPM_VD_STATUS_CONNECTED) == 0) { ++ if (time_after(jiffies, ++ vtpms->disconnect_time + HZ * 10)) { ++ rc = -ENOENT; ++ } else { ++ goto queue_it; ++ } ++ } else { ++ /* ++ * Send all queued packets. ++ */ ++ if (_vtpm_send_queued(chip) == 0) { ++ ++ vtpms->current_request = t; ++ ++ rc = vtpm_vd_send(vtpms->tpm_private, ++ buf, ++ count, ++ t); ++ /* ++ * The generic TPM driver will call ++ * the function to receive the response. ++ */ ++ if (rc < 0) { ++ vtpms->current_request = NULL; ++ goto queue_it; ++ } ++ } else { ++queue_it: ++ if (!transmission_set_req_buffer(t, buf, count)) { ++ transmission_free(t); ++ rc = -ENOMEM; ++ goto exit; ++ } ++ /* ++ * An error occurred. Don't event try ++ * to send the current request. Just ++ * queue it. ++ */ ++ spin_lock_irqsave(&vtpms->req_list_lock, flags); ++ vtpms->flags |= DATAEX_FLAG_QUEUED_ONLY; ++ list_add_tail(&t->next, &vtpms->queued_requests); ++ spin_unlock_irqrestore(&vtpms->req_list_lock, flags); ++ } ++ } ++ ++exit: ++ return rc; ++} ++ ++ ++/* ++ * Send all queued requests. ++ */ ++static int _vtpm_send_queued(struct tpm_chip *chip) ++{ ++ int rc; ++ int error = 0; ++ long flags; ++ unsigned char buffer[1]; ++ struct vtpm_state *vtpms; ++ vtpms = (struct vtpm_state *)chip_get_private(chip); ++ ++ spin_lock_irqsave(&vtpms->req_list_lock, flags); ++ ++ while (!list_empty(&vtpms->queued_requests)) { ++ /* ++ * Need to dequeue them. ++ * Read the result into a dummy buffer. ++ */ ++ struct transmission *qt = (struct transmission *) ++ vtpms->queued_requests.next; ++ list_del(&qt->next); ++ vtpms->current_request = qt; ++ spin_unlock_irqrestore(&vtpms->req_list_lock, flags); ++ ++ rc = vtpm_vd_send(vtpms->tpm_private, ++ qt->request, ++ qt->request_len, ++ qt); ++ ++ if (rc < 0) { ++ spin_lock_irqsave(&vtpms->req_list_lock, flags); ++ if ((qt = vtpms->current_request) != NULL) { ++ /* ++ * requeue it at the beginning ++ * of the list ++ */ ++ list_add(&qt->next, ++ &vtpms->queued_requests); ++ } ++ vtpms->current_request = NULL; ++ error = 1; ++ break; ++ } ++ /* ++ * After this point qt is not valid anymore! ++ * It is freed when the front-end is delivering ++ * the data by calling tpm_recv ++ */ ++ /* ++ * Receive response into provided dummy buffer ++ */ ++ rc = vtpm_recv(chip, buffer, sizeof(buffer)); ++ spin_lock_irqsave(&vtpms->req_list_lock, flags); ++ } ++ ++ spin_unlock_irqrestore(&vtpms->req_list_lock, flags); ++ ++ return error; ++} ++ ++static void vtpm_cancel(struct tpm_chip *chip) ++{ ++ unsigned long flags; ++ struct vtpm_state *vtpms = (struct vtpm_state *)chip_get_private(chip); ++ ++ spin_lock_irqsave(&vtpms->resp_list_lock,flags); ++ ++ if (!vtpms->current_response && vtpms->current_request) { ++ spin_unlock_irqrestore(&vtpms->resp_list_lock, flags); ++ interruptible_sleep_on(&vtpms->resp_wait_queue); ++ spin_lock_irqsave(&vtpms->resp_list_lock,flags); ++ } ++ ++ if (vtpms->current_response) { ++ struct transmission *t = vtpms->current_response; ++ vtpms->current_response = NULL; ++ transmission_free(t); ++ } ++ ++ spin_unlock_irqrestore(&vtpms->resp_list_lock,flags); ++} ++ ++static u8 vtpm_status(struct tpm_chip *chip) ++{ ++ u8 rc = 0; ++ unsigned long flags; ++ struct vtpm_state *vtpms; ++ ++ vtpms = (struct vtpm_state *)chip_get_private(chip); ++ ++ spin_lock_irqsave(&vtpms->resp_list_lock, flags); ++ /* ++ * Data are available if: ++ * - there's a current response ++ * - the last packet was queued only (this is fake, but necessary to ++ * get the generic TPM layer to call the receive function.) ++ */ ++ if (vtpms->current_response || ++ 0 != (vtpms->flags & DATAEX_FLAG_QUEUED_ONLY)) { ++ rc = STATUS_DATA_AVAIL; ++ } else if (!vtpms->current_response && !vtpms->current_request) { ++ rc = STATUS_READY; ++ } ++ ++ spin_unlock_irqrestore(&vtpms->resp_list_lock, flags); ++ return rc; ++} ++ ++static struct file_operations vtpm_ops = { ++ .owner = THIS_MODULE, ++ .llseek = no_llseek, ++ .open = tpm_open, ++ .read = tpm_read, ++ .write = tpm_write, ++ .release = tpm_release, ++}; ++ ++static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL); ++static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL); ++static DEVICE_ATTR(enabled, S_IRUGO, tpm_show_enabled, NULL); ++static DEVICE_ATTR(active, S_IRUGO, tpm_show_active, NULL); ++static DEVICE_ATTR(owned, S_IRUGO, tpm_show_owned, NULL); ++static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated, ++ NULL); ++static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps, NULL); ++static DEVICE_ATTR(cancel, S_IWUSR |S_IWGRP, NULL, tpm_store_cancel); ++ ++static struct attribute *vtpm_attrs[] = { ++ &dev_attr_pubek.attr, ++ &dev_attr_pcrs.attr, ++ &dev_attr_enabled.attr, ++ &dev_attr_active.attr, ++ &dev_attr_owned.attr, ++ &dev_attr_temp_deactivated.attr, ++ &dev_attr_caps.attr, ++ &dev_attr_cancel.attr, ++ NULL, ++}; ++ ++static struct attribute_group vtpm_attr_grp = { .attrs = vtpm_attrs }; ++ ++#define TPM_LONG_TIMEOUT (10 * 60 * HZ) ++ ++static struct tpm_vendor_specific tpm_vtpm = { ++ .recv = vtpm_recv, ++ .send = vtpm_send, ++ .cancel = vtpm_cancel, ++ .status = vtpm_status, ++ .req_complete_mask = STATUS_BUSY | STATUS_DATA_AVAIL, ++ .req_complete_val = STATUS_DATA_AVAIL, ++ .req_canceled = STATUS_READY, ++ .attr_group = &vtpm_attr_grp, ++ .miscdev = { ++ .fops = &vtpm_ops, ++ }, ++ .duration = { ++ TPM_LONG_TIMEOUT, ++ TPM_LONG_TIMEOUT, ++ TPM_LONG_TIMEOUT, ++ }, ++}; ++ ++struct tpm_chip *init_vtpm(struct device *dev, ++ struct tpm_private *tp) ++{ ++ long rc; ++ struct tpm_chip *chip; ++ struct vtpm_state *vtpms; ++ ++ vtpms = kzalloc(sizeof(struct vtpm_state), GFP_KERNEL); ++ if (!vtpms) ++ return ERR_PTR(-ENOMEM); ++ ++ vtpm_state_init(vtpms); ++ vtpms->tpm_private = tp; ++ ++ chip = tpm_register_hardware(dev, &tpm_vtpm); ++ if (!chip) { ++ rc = -ENODEV; ++ goto err_free_mem; ++ } ++ ++ chip_set_private(chip, vtpms); ++ ++ return chip; ++ ++err_free_mem: ++ kfree(vtpms); ++ ++ return ERR_PTR(rc); ++} ++ ++void cleanup_vtpm(struct device *dev) ++{ ++ struct tpm_chip *chip = dev_get_drvdata(dev); ++ struct vtpm_state *vtpms = (struct vtpm_state*)chip_get_private(chip); ++ tpm_remove_hardware(dev); ++ kfree(vtpms); ++} +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/drivers/char/tpm/tpm_vtpm.h 2009-12-04 10:44:41.000000000 +0100 +@@ -0,0 +1,55 @@ ++#ifndef TPM_VTPM_H ++#define TPM_VTPM_H ++ ++struct tpm_chip; ++struct tpm_private; ++ ++struct vtpm_state { ++ struct transmission *current_request; ++ spinlock_t req_list_lock; ++ wait_queue_head_t req_wait_queue; ++ ++ struct list_head queued_requests; ++ ++ struct transmission *current_response; ++ spinlock_t resp_list_lock; ++ wait_queue_head_t resp_wait_queue; // processes waiting for responses ++ ++ u8 vd_status; ++ u8 flags; ++ ++ unsigned long disconnect_time; ++ ++ /* ++ * The following is a private structure of the underlying ++ * driver. It is passed as parameter in the send function. ++ */ ++ struct tpm_private *tpm_private; ++}; ++ ++ ++enum vdev_status { ++ TPM_VD_STATUS_DISCONNECTED = 0x0, ++ TPM_VD_STATUS_CONNECTED = 0x1 ++}; ++ ++/* this function is called from tpm_vtpm.c */ ++int vtpm_vd_send(struct tpm_private * tp, ++ const u8 * buf, size_t count, void *ptr); ++ ++/* these functions are offered by tpm_vtpm.c */ ++struct tpm_chip *init_vtpm(struct device *, ++ struct tpm_private *); ++void cleanup_vtpm(struct device *); ++int vtpm_vd_recv(const struct tpm_chip* chip, ++ const unsigned char *buffer, size_t count, void *ptr); ++void vtpm_vd_status(const struct tpm_chip *, u8 status); ++ ++static inline struct tpm_private *tpm_private_from_dev(struct device *dev) ++{ ++ struct tpm_chip *chip = dev_get_drvdata(dev); ++ struct vtpm_state *vtpms = chip_get_private(chip); ++ return vtpms->tpm_private; ++} ++ ++#endif +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/drivers/char/tpm/tpm_xen.c 2009-12-04 10:44:41.000000000 +0100 +@@ -0,0 +1,722 @@ ++/* ++ * Copyright (c) 2005, IBM Corporation ++ * ++ * Author: Stefan Berger, stefanb@us.ibm.com ++ * Grant table support: Mahadevan Gomathisankaran ++ * ++ * This code has been derived from drivers/xen/netfront/netfront.c ++ * ++ * Copyright (c) 2002-2004, K A Fraser ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License version 2 ++ * as published by the Free Software Foundation; or, when distributed ++ * separately from the Linux kernel or incorporated into other ++ * software packages, subject to the following license: ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this source file (the "Software"), to deal in the Software without ++ * restriction, including without limitation the rights to use, copy, modify, ++ * merge, publish, distribute, sublicense, and/or sell copies of the Software, ++ * and to permit persons to whom the Software is furnished to do so, subject to ++ * the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS ++ * IN THE SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "tpm.h" ++#include "tpm_vtpm.h" ++ ++#undef DEBUG ++ ++/* local structures */ ++struct tpm_private { ++ struct tpm_chip *chip; ++ ++ tpmif_tx_interface_t *tx; ++ atomic_t refcnt; ++ unsigned int irq; ++ u8 is_connected; ++ u8 is_suspended; ++ ++ spinlock_t tx_lock; ++ ++ struct tx_buffer *tx_buffers[TPMIF_TX_RING_SIZE]; ++ ++ atomic_t tx_busy; ++ void *tx_remember; ++ ++ domid_t backend_id; ++ wait_queue_head_t wait_q; ++ ++ struct xenbus_device *dev; ++ int ring_ref; ++}; ++ ++struct tx_buffer { ++ unsigned int size; // available space in data ++ unsigned int len; // used space in data ++ unsigned char *data; // pointer to a page ++}; ++ ++ ++/* locally visible variables */ ++static grant_ref_t gref_head; ++static struct tpm_private *my_priv; ++ ++/* local function prototypes */ ++static irqreturn_t tpmif_int(int irq, ++ void *tpm_priv, ++ struct pt_regs *ptregs); ++static void tpmif_rx_action(unsigned long unused); ++static int tpmif_connect(struct xenbus_device *dev, ++ struct tpm_private *tp, ++ domid_t domid); ++static DECLARE_TASKLET(tpmif_rx_tasklet, tpmif_rx_action, 0); ++static int tpmif_allocate_tx_buffers(struct tpm_private *tp); ++static void tpmif_free_tx_buffers(struct tpm_private *tp); ++static void tpmif_set_connected_state(struct tpm_private *tp, ++ u8 newstate); ++static int tpm_xmit(struct tpm_private *tp, ++ const u8 * buf, size_t count, int userbuffer, ++ void *remember); ++static void destroy_tpmring(struct tpm_private *tp); ++void __exit tpmif_exit(void); ++ ++#define DPRINTK(fmt, args...) \ ++ pr_debug("xen_tpm_fr (%s:%d) " fmt, __FUNCTION__, __LINE__, ##args) ++#define IPRINTK(fmt, args...) \ ++ printk(KERN_INFO "xen_tpm_fr: " fmt, ##args) ++#define WPRINTK(fmt, args...) \ ++ printk(KERN_WARNING "xen_tpm_fr: " fmt, ##args) ++ ++#define GRANT_INVALID_REF 0 ++ ++ ++static inline int ++tx_buffer_copy(struct tx_buffer *txb, const u8 *src, int len, ++ int isuserbuffer) ++{ ++ int copied = len; ++ ++ if (len > txb->size) ++ copied = txb->size; ++ if (isuserbuffer) { ++ if (copy_from_user(txb->data, src, copied)) ++ return -EFAULT; ++ } else { ++ memcpy(txb->data, src, copied); ++ } ++ txb->len = len; ++ return copied; ++} ++ ++static inline struct tx_buffer *tx_buffer_alloc(void) ++{ ++ struct tx_buffer *txb; ++ ++ txb = kzalloc(sizeof(struct tx_buffer), GFP_KERNEL); ++ if (!txb) ++ return NULL; ++ ++ txb->len = 0; ++ txb->size = PAGE_SIZE; ++ txb->data = (unsigned char *)__get_free_page(GFP_KERNEL); ++ if (txb->data == NULL) { ++ kfree(txb); ++ txb = NULL; ++ } ++ ++ return txb; ++} ++ ++ ++static inline void tx_buffer_free(struct tx_buffer *txb) ++{ ++ if (txb) { ++ free_page((long)txb->data); ++ kfree(txb); ++ } ++} ++ ++/************************************************************** ++ Utility function for the tpm_private structure ++**************************************************************/ ++static void tpm_private_init(struct tpm_private *tp) ++{ ++ spin_lock_init(&tp->tx_lock); ++ init_waitqueue_head(&tp->wait_q); ++ atomic_set(&tp->refcnt, 1); ++} ++ ++static void tpm_private_put(void) ++{ ++ if (!atomic_dec_and_test(&my_priv->refcnt)) ++ return; ++ ++ tpmif_free_tx_buffers(my_priv); ++ kfree(my_priv); ++ my_priv = NULL; ++} ++ ++static struct tpm_private *tpm_private_get(void) ++{ ++ int err; ++ ++ if (my_priv) { ++ atomic_inc(&my_priv->refcnt); ++ return my_priv; ++ } ++ ++ my_priv = kzalloc(sizeof(struct tpm_private), GFP_KERNEL); ++ if (!my_priv) ++ return NULL; ++ ++ tpm_private_init(my_priv); ++ err = tpmif_allocate_tx_buffers(my_priv); ++ if (err < 0) ++ tpm_private_put(); ++ ++ return my_priv; ++} ++ ++/************************************************************** ++ ++ The interface to let the tpm plugin register its callback ++ function and send data to another partition using this module ++ ++**************************************************************/ ++ ++static DEFINE_MUTEX(suspend_lock); ++/* ++ * Send data via this module by calling this function ++ */ ++int vtpm_vd_send(struct tpm_private *tp, ++ const u8 * buf, size_t count, void *ptr) ++{ ++ int sent; ++ ++ mutex_lock(&suspend_lock); ++ sent = tpm_xmit(tp, buf, count, 0, ptr); ++ mutex_unlock(&suspend_lock); ++ ++ return sent; ++} ++ ++/************************************************************** ++ XENBUS support code ++**************************************************************/ ++ ++static int setup_tpmring(struct xenbus_device *dev, ++ struct tpm_private *tp) ++{ ++ tpmif_tx_interface_t *sring; ++ int err; ++ ++ tp->ring_ref = GRANT_INVALID_REF; ++ ++ sring = (void *)__get_free_page(GFP_KERNEL); ++ if (!sring) { ++ xenbus_dev_fatal(dev, -ENOMEM, "allocating shared ring"); ++ return -ENOMEM; ++ } ++ tp->tx = sring; ++ ++ err = xenbus_grant_ring(dev, virt_to_mfn(tp->tx)); ++ if (err < 0) { ++ free_page((unsigned long)sring); ++ tp->tx = NULL; ++ xenbus_dev_fatal(dev, err, "allocating grant reference"); ++ goto fail; ++ } ++ tp->ring_ref = err; ++ ++ err = tpmif_connect(dev, tp, dev->otherend_id); ++ if (err) ++ goto fail; ++ ++ return 0; ++fail: ++ destroy_tpmring(tp); ++ return err; ++} ++ ++ ++static void destroy_tpmring(struct tpm_private *tp) ++{ ++ tpmif_set_connected_state(tp, 0); ++ ++ if (tp->ring_ref != GRANT_INVALID_REF) { ++ gnttab_end_foreign_access(tp->ring_ref, (unsigned long)tp->tx); ++ tp->ring_ref = GRANT_INVALID_REF; ++ tp->tx = NULL; ++ } ++ ++ if (tp->irq) ++ unbind_from_irqhandler(tp->irq, tp); ++ ++ tp->irq = 0; ++} ++ ++ ++static int talk_to_backend(struct xenbus_device *dev, ++ struct tpm_private *tp) ++{ ++ const char *message = NULL; ++ int err; ++ struct xenbus_transaction xbt; ++ ++ err = setup_tpmring(dev, tp); ++ if (err) { ++ xenbus_dev_fatal(dev, err, "setting up ring"); ++ goto out; ++ } ++ ++again: ++ err = xenbus_transaction_start(&xbt); ++ if (err) { ++ xenbus_dev_fatal(dev, err, "starting transaction"); ++ goto destroy_tpmring; ++ } ++ ++ err = xenbus_printf(xbt, dev->nodename, ++ "ring-ref","%u", tp->ring_ref); ++ if (err) { ++ message = "writing ring-ref"; ++ goto abort_transaction; ++ } ++ ++ err = xenbus_printf(xbt, dev->nodename, "event-channel", "%u", ++ irq_to_evtchn_port(tp->irq)); ++ if (err) { ++ message = "writing event-channel"; ++ goto abort_transaction; ++ } ++ ++ err = xenbus_transaction_end(xbt, 0); ++ if (err == -EAGAIN) ++ goto again; ++ if (err) { ++ xenbus_dev_fatal(dev, err, "completing transaction"); ++ goto destroy_tpmring; ++ } ++ ++ xenbus_switch_state(dev, XenbusStateConnected); ++ ++ return 0; ++ ++abort_transaction: ++ xenbus_transaction_end(xbt, 1); ++ if (message) ++ xenbus_dev_error(dev, err, "%s", message); ++destroy_tpmring: ++ destroy_tpmring(tp); ++out: ++ return err; ++} ++ ++/** ++ * Callback received when the backend's state changes. ++ */ ++static void backend_changed(struct xenbus_device *dev, ++ enum xenbus_state backend_state) ++{ ++ struct tpm_private *tp = tpm_private_from_dev(&dev->dev); ++ DPRINTK("\n"); ++ ++ switch (backend_state) { ++ case XenbusStateInitialising: ++ case XenbusStateInitWait: ++ case XenbusStateInitialised: ++ case XenbusStateReconfiguring: ++ case XenbusStateReconfigured: ++ case XenbusStateUnknown: ++ break; ++ ++ case XenbusStateConnected: ++ tpmif_set_connected_state(tp, 1); ++ break; ++ ++ case XenbusStateClosing: ++ tpmif_set_connected_state(tp, 0); ++ xenbus_frontend_closed(dev); ++ break; ++ ++ case XenbusStateClosed: ++ tpmif_set_connected_state(tp, 0); ++ if (tp->is_suspended == 0) ++ device_unregister(&dev->dev); ++ xenbus_frontend_closed(dev); ++ break; ++ } ++} ++ ++static int tpmfront_probe(struct xenbus_device *dev, ++ const struct xenbus_device_id *id) ++{ ++ int err; ++ int handle; ++ struct tpm_private *tp = tpm_private_get(); ++ ++ if (!tp) ++ return -ENOMEM; ++ ++ tp->chip = init_vtpm(&dev->dev, tp); ++ if (IS_ERR(tp->chip)) ++ return PTR_ERR(tp->chip); ++ ++ err = xenbus_scanf(XBT_NIL, dev->nodename, ++ "handle", "%i", &handle); ++ if (XENBUS_EXIST_ERR(err)) ++ return err; ++ ++ if (err < 0) { ++ xenbus_dev_fatal(dev,err,"reading virtual-device"); ++ return err; ++ } ++ ++ tp->dev = dev; ++ ++ err = talk_to_backend(dev, tp); ++ if (err) { ++ tpm_private_put(); ++ return err; ++ } ++ ++ return 0; ++} ++ ++ ++static int tpmfront_remove(struct xenbus_device *dev) ++{ ++ struct tpm_private *tp = tpm_private_from_dev(&dev->dev); ++ destroy_tpmring(tp); ++ cleanup_vtpm(&dev->dev); ++ return 0; ++} ++ ++static int tpmfront_suspend(struct xenbus_device *dev) ++{ ++ struct tpm_private *tp = tpm_private_from_dev(&dev->dev); ++ u32 ctr; ++ ++ /* Take the lock, preventing any application from sending. */ ++ mutex_lock(&suspend_lock); ++ tp->is_suspended = 1; ++ ++ for (ctr = 0; atomic_read(&tp->tx_busy); ctr++) { ++ if ((ctr % 10) == 0) ++ printk("TPM-FE [INFO]: Waiting for outstanding " ++ "request.\n"); ++ /* Wait for a request to be responded to. */ ++ interruptible_sleep_on_timeout(&tp->wait_q, 100); ++ } ++ ++ return 0; ++} ++ ++static int tpmfront_suspend_finish(struct tpm_private *tp) ++{ ++ tp->is_suspended = 0; ++ /* Allow applications to send again. */ ++ mutex_unlock(&suspend_lock); ++ return 0; ++} ++ ++static int tpmfront_suspend_cancel(struct xenbus_device *dev) ++{ ++ struct tpm_private *tp = tpm_private_from_dev(&dev->dev); ++ return tpmfront_suspend_finish(tp); ++} ++ ++static int tpmfront_resume(struct xenbus_device *dev) ++{ ++ struct tpm_private *tp = tpm_private_from_dev(&dev->dev); ++ destroy_tpmring(tp); ++ return talk_to_backend(dev, tp); ++} ++ ++static int tpmif_connect(struct xenbus_device *dev, ++ struct tpm_private *tp, ++ domid_t domid) ++{ ++ int err; ++ ++ tp->backend_id = domid; ++ ++ err = bind_listening_port_to_irqhandler( ++ domid, tpmif_int, SA_SAMPLE_RANDOM, "tpmif", tp); ++ if (err <= 0) { ++ WPRINTK("bind_listening_port_to_irqhandler failed " ++ "(err=%d)\n", err); ++ return err; ++ } ++ tp->irq = err; ++ ++ return 0; ++} ++ ++static struct xenbus_device_id tpmfront_ids[] = { ++ { "vtpm" }, ++ { "" } ++}; ++ ++static struct xenbus_driver tpmfront = { ++ .name = "vtpm", ++ .owner = THIS_MODULE, ++ .ids = tpmfront_ids, ++ .probe = tpmfront_probe, ++ .remove = tpmfront_remove, ++ .resume = tpmfront_resume, ++ .otherend_changed = backend_changed, ++ .suspend = tpmfront_suspend, ++ .suspend_cancel = tpmfront_suspend_cancel, ++}; ++ ++static void __init init_tpm_xenbus(void) ++{ ++ xenbus_register_frontend(&tpmfront); ++} ++ ++static int tpmif_allocate_tx_buffers(struct tpm_private *tp) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < TPMIF_TX_RING_SIZE; i++) { ++ tp->tx_buffers[i] = tx_buffer_alloc(); ++ if (!tp->tx_buffers[i]) { ++ tpmif_free_tx_buffers(tp); ++ return -ENOMEM; ++ } ++ } ++ return 0; ++} ++ ++static void tpmif_free_tx_buffers(struct tpm_private *tp) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < TPMIF_TX_RING_SIZE; i++) ++ tx_buffer_free(tp->tx_buffers[i]); ++} ++ ++static void tpmif_rx_action(unsigned long priv) ++{ ++ struct tpm_private *tp = (struct tpm_private *)priv; ++ int i = 0; ++ unsigned int received; ++ unsigned int offset = 0; ++ u8 *buffer; ++ tpmif_tx_request_t *tx = &tp->tx->ring[i].req; ++ ++ atomic_set(&tp->tx_busy, 0); ++ wake_up_interruptible(&tp->wait_q); ++ ++ received = tx->size; ++ ++ buffer = kmalloc(received, GFP_ATOMIC); ++ if (!buffer) ++ return; ++ ++ for (i = 0; i < TPMIF_TX_RING_SIZE && offset < received; i++) { ++ struct tx_buffer *txb = tp->tx_buffers[i]; ++ tpmif_tx_request_t *tx; ++ unsigned int tocopy; ++ ++ tx = &tp->tx->ring[i].req; ++ tocopy = tx->size; ++ if (tocopy > PAGE_SIZE) ++ tocopy = PAGE_SIZE; ++ ++ memcpy(&buffer[offset], txb->data, tocopy); ++ ++ gnttab_release_grant_reference(&gref_head, tx->ref); ++ ++ offset += tocopy; ++ } ++ ++ vtpm_vd_recv(tp->chip, buffer, received, tp->tx_remember); ++ kfree(buffer); ++} ++ ++ ++static irqreturn_t tpmif_int(int irq, void *tpm_priv, struct pt_regs *ptregs) ++{ ++ struct tpm_private *tp = tpm_priv; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&tp->tx_lock, flags); ++ tpmif_rx_tasklet.data = (unsigned long)tp; ++ tasklet_schedule(&tpmif_rx_tasklet); ++ spin_unlock_irqrestore(&tp->tx_lock, flags); ++ ++ return IRQ_HANDLED; ++} ++ ++ ++static int tpm_xmit(struct tpm_private *tp, ++ const u8 * buf, size_t count, int isuserbuffer, ++ void *remember) ++{ ++ tpmif_tx_request_t *tx; ++ TPMIF_RING_IDX i; ++ unsigned int offset = 0; ++ ++ spin_lock_irq(&tp->tx_lock); ++ ++ if (unlikely(atomic_read(&tp->tx_busy))) { ++ printk("tpm_xmit: There's an outstanding request/response " ++ "on the way!\n"); ++ spin_unlock_irq(&tp->tx_lock); ++ return -EBUSY; ++ } ++ ++ if (tp->is_connected != 1) { ++ spin_unlock_irq(&tp->tx_lock); ++ return -EIO; ++ } ++ ++ for (i = 0; count > 0 && i < TPMIF_TX_RING_SIZE; i++) { ++ struct tx_buffer *txb = tp->tx_buffers[i]; ++ int copied; ++ ++ if (!txb) { ++ DPRINTK("txb (i=%d) is NULL. buffers initilized?\n" ++ "Not transmitting anything!\n", i); ++ spin_unlock_irq(&tp->tx_lock); ++ return -EFAULT; ++ } ++ ++ copied = tx_buffer_copy(txb, &buf[offset], count, ++ isuserbuffer); ++ if (copied < 0) { ++ /* An error occurred */ ++ spin_unlock_irq(&tp->tx_lock); ++ return copied; ++ } ++ count -= copied; ++ offset += copied; ++ ++ tx = &tp->tx->ring[i].req; ++ tx->addr = virt_to_machine(txb->data); ++ tx->size = txb->len; ++ tx->unused = 0; ++ ++ DPRINTK("First 4 characters sent by TPM-FE are " ++ "0x%02x 0x%02x 0x%02x 0x%02x\n", ++ txb->data[0],txb->data[1],txb->data[2],txb->data[3]); ++ ++ /* Get the granttable reference for this page. */ ++ tx->ref = gnttab_claim_grant_reference(&gref_head); ++ if (tx->ref == -ENOSPC) { ++ spin_unlock_irq(&tp->tx_lock); ++ DPRINTK("Grant table claim reference failed in " ++ "func:%s line:%d file:%s\n", ++ __FUNCTION__, __LINE__, __FILE__); ++ return -ENOSPC; ++ } ++ gnttab_grant_foreign_access_ref(tx->ref, ++ tp->backend_id, ++ virt_to_mfn(txb->data), ++ 0 /*RW*/); ++ wmb(); ++ } ++ ++ atomic_set(&tp->tx_busy, 1); ++ tp->tx_remember = remember; ++ ++ mb(); ++ ++ notify_remote_via_irq(tp->irq); ++ ++ spin_unlock_irq(&tp->tx_lock); ++ return offset; ++} ++ ++ ++static void tpmif_notify_upperlayer(struct tpm_private *tp) ++{ ++ /* Notify upper layer about the state of the connection to the BE. */ ++ vtpm_vd_status(tp->chip, (tp->is_connected ++ ? TPM_VD_STATUS_CONNECTED ++ : TPM_VD_STATUS_DISCONNECTED)); ++} ++ ++ ++static void tpmif_set_connected_state(struct tpm_private *tp, u8 is_connected) ++{ ++ /* ++ * Don't notify upper layer if we are in suspend mode and ++ * should disconnect - assumption is that we will resume ++ * The mutex keeps apps from sending. ++ */ ++ if (is_connected == 0 && tp->is_suspended == 1) ++ return; ++ ++ /* ++ * Unlock the mutex if we are connected again ++ * after being suspended - now resuming. ++ * This also removes the suspend state. ++ */ ++ if (is_connected == 1 && tp->is_suspended == 1) ++ tpmfront_suspend_finish(tp); ++ ++ if (is_connected != tp->is_connected) { ++ tp->is_connected = is_connected; ++ tpmif_notify_upperlayer(tp); ++ } ++} ++ ++ ++ ++/* ================================================================= ++ * Initialization function. ++ * ================================================================= ++ */ ++ ++ ++static int __init tpmif_init(void) ++{ ++ struct tpm_private *tp; ++ ++ if (is_initial_xendomain()) ++ return -EPERM; ++ ++ tp = tpm_private_get(); ++ if (!tp) ++ return -ENOMEM; ++ ++ IPRINTK("Initialising the vTPM driver.\n"); ++ if (gnttab_alloc_grant_references(TPMIF_TX_RING_SIZE, ++ &gref_head) < 0) { ++ tpm_private_put(); ++ return -EFAULT; ++ } ++ ++ init_tpm_xenbus(); ++ return 0; ++} ++ ++ ++module_init(tpmif_init); ++ ++MODULE_LICENSE("Dual BSD/GPL"); +--- sle11sp1-2010-03-22.orig/drivers/edac/edac_mc.c 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/edac/edac_mc.c 2009-12-04 10:44:41.000000000 +0100 +@@ -578,6 +578,10 @@ static void edac_mc_scrub_block(unsigned + + debugf3("%s()\n", __func__); + ++#ifdef CONFIG_XEN ++ page = mfn_to_local_pfn(page); ++#endif ++ + /* ECC error page was not in our memory. Ignore it. */ + if (!pfn_valid(page)) + return; +--- sle11sp1-2010-03-22.orig/drivers/firmware/dell_rbu.c 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/firmware/dell_rbu.c 2009-12-04 10:44:41.000000000 +0100 +@@ -169,9 +169,28 @@ static int create_packet(void *data, siz + spin_lock(&rbu_data.lock); + goto out_alloc_packet_array; + } ++#ifdef CONFIG_XEN ++ if (ordernum && xen_create_contiguous_region( ++ (unsigned long)packet_data_temp_buf, ordernum, 0)) { ++ free_pages((unsigned long)packet_data_temp_buf, ++ ordernum); ++ printk(KERN_WARNING ++ "dell_rbu:%s: failed to adjust new " ++ "packet\n", __func__); ++ retval = -ENOMEM; ++ spin_lock(&rbu_data.lock); ++ goto out_alloc_packet_array; ++ } ++#endif + +- if ((unsigned long)virt_to_phys(packet_data_temp_buf) ++ if ((unsigned long)virt_to_bus(packet_data_temp_buf) + < allocation_floor) { ++#ifdef CONFIG_XEN ++ if (ordernum) ++ xen_destroy_contiguous_region( ++ (unsigned long)packet_data_temp_buf, ++ ordernum); ++#endif + pr_debug("packet 0x%lx below floor at 0x%lx.\n", + (unsigned long)virt_to_phys( + packet_data_temp_buf), +@@ -185,7 +204,7 @@ static int create_packet(void *data, siz + newpacket->data = packet_data_temp_buf; + + pr_debug("create_packet: newpacket at physical addr %lx\n", +- (unsigned long)virt_to_phys(newpacket->data)); ++ (unsigned long)virt_to_bus(newpacket->data)); + + /* packets may not have fixed size */ + newpacket->length = length; +@@ -204,7 +223,7 @@ out_alloc_packet_array: + /* always free packet array */ + for (;idx>0;idx--) { + pr_debug("freeing unused packet below floor 0x%lx.\n", +- (unsigned long)virt_to_phys( ++ (unsigned long)virt_to_bus( + invalid_addr_packet_array[idx-1])); + free_pages((unsigned long)invalid_addr_packet_array[idx-1], + ordernum); +@@ -348,6 +367,13 @@ static void packet_empty_list(void) + * to make sure there are no stale RBU packets left in memory + */ + memset(newpacket->data, 0, rbu_data.packetsize); ++#ifdef CONFIG_XEN ++ if (newpacket->ordernum) ++ xen_destroy_contiguous_region( ++ (unsigned long)newpacket->data, ++ newpacket->ordernum); ++#endif ++ + free_pages((unsigned long) newpacket->data, + newpacket->ordernum); + kfree(newpacket); +@@ -402,7 +428,9 @@ static int img_update_realloc(unsigned l + { + unsigned char *image_update_buffer = NULL; + unsigned long rc; ++#ifndef CONFIG_XEN + unsigned long img_buf_phys_addr; ++#endif + int ordernum; + int dma_alloc = 0; + +@@ -433,15 +461,19 @@ static int img_update_realloc(unsigned l + + spin_unlock(&rbu_data.lock); + ++#ifndef CONFIG_XEN + ordernum = get_order(size); + image_update_buffer = + (unsigned char *) __get_free_pages(GFP_KERNEL, ordernum); + + img_buf_phys_addr = +- (unsigned long) virt_to_phys(image_update_buffer); ++ (unsigned long) virt_to_bus(image_update_buffer); + + if (img_buf_phys_addr > BIOS_SCAN_LIMIT) { + free_pages((unsigned long) image_update_buffer, ordernum); ++#else ++ { ++#endif + ordernum = -1; + image_update_buffer = dma_alloc_coherent(NULL, size, + &dell_rbu_dmaaddr, GFP_KERNEL); +@@ -689,6 +721,12 @@ static struct bin_attribute rbu_packet_s + static int __init dcdrbu_init(void) + { + int rc; ++ ++#ifdef CONFIG_XEN ++ if (!is_initial_xendomain()) ++ return -ENODEV; ++#endif ++ + spin_lock_init(&rbu_data.lock); + + init_packet_head(); +--- sle11sp1-2010-03-22.orig/drivers/ide/ide-lib.c 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/ide/ide-lib.c 2009-12-04 10:44:41.000000000 +0100 +@@ -18,12 +18,12 @@ void ide_toggle_bounce(ide_drive_t *driv + { + u64 addr = BLK_BOUNCE_HIGH; /* dma64_addr_t */ + +- if (!PCI_DMA_BUS_IS_PHYS) { +- addr = BLK_BOUNCE_ANY; +- } else if (on && drive->media == ide_disk) { ++ if (on && drive->media == ide_disk) { + struct device *dev = drive->hwif->dev; + +- if (dev && dev->dma_mask) ++ if (!PCI_DMA_BUS_IS_PHYS) ++ addr = BLK_BOUNCE_ANY; ++ else if (dev && dev->dma_mask) + addr = *dev->dma_mask; + } + +--- sle11sp1-2010-03-22.orig/drivers/oprofile/buffer_sync.c 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/oprofile/buffer_sync.c 2009-12-04 10:44:41.000000000 +0100 +@@ -8,6 +8,10 @@ + * @author Barry Kasindorf + * @author Robert Richter + * ++ * Modified by Aravind Menon for Xen ++ * These modifications are: ++ * Copyright (C) 2005 Hewlett-Packard Co. ++ * + * This is the core of the buffer management. Each + * CPU buffer is processed and entered into the + * global event buffer. Such processing is necessary +@@ -42,6 +46,8 @@ static cpumask_var_t marked_cpus; + static DEFINE_SPINLOCK(task_mortuary); + static void process_task_mortuary(void); + ++static int cpu_current_domain[NR_CPUS]; ++ + /* Take ownership of the task struct and place it on the + * list for processing. Only after two full buffer syncs + * does the task eventually get freed, because by then +@@ -60,7 +66,6 @@ task_free_notify(struct notifier_block * + return NOTIFY_OK; + } + +- + /* The task is on its way out. A sync of the buffer means we can catch + * any remaining samples for this task. + */ +@@ -153,6 +158,11 @@ static void end_sync(void) + int sync_start(void) + { + int err; ++ int i; ++ ++ for (i = 0; i < NR_CPUS; i++) { ++ cpu_current_domain[i] = COORDINATOR_DOMAIN; ++ } + + if (!zalloc_cpumask_var(&marked_cpus, GFP_KERNEL)) + return -ENOMEM; +@@ -284,13 +294,29 @@ static void add_cpu_switch(int i) + last_cookie = INVALID_COOKIE; + } + +-static void add_kernel_ctx_switch(unsigned int in_kernel) ++static void add_cpu_mode_switch(unsigned int cpu_mode) + { + add_event_entry(ESCAPE_CODE); +- if (in_kernel) ++ switch (cpu_mode) { ++ case CPU_MODE_USER: ++ add_event_entry(USER_ENTER_SWITCH_CODE); ++ break; ++ case CPU_MODE_KERNEL: + add_event_entry(KERNEL_ENTER_SWITCH_CODE); +- else +- add_event_entry(KERNEL_EXIT_SWITCH_CODE); ++ break; ++ case CPU_MODE_XEN: ++ add_event_entry(XEN_ENTER_SWITCH_CODE); ++ break; ++ default: ++ break; ++ } ++} ++ ++static void add_domain_switch(unsigned long domain_id) ++{ ++ add_event_entry(ESCAPE_CODE); ++ add_event_entry(DOMAIN_SWITCH_CODE); ++ add_event_entry(domain_id); + } + + static void +@@ -371,12 +397,12 @@ static inline void add_sample_entry(unsi + * for later lookup from userspace. Return 0 on failure. + */ + static int +-add_sample(struct mm_struct *mm, struct op_sample *s, int in_kernel) ++add_sample(struct mm_struct *mm, struct op_sample *s, int cpu_mode) + { + unsigned long cookie; + off_t offset; + +- if (in_kernel) { ++ if (cpu_mode >= CPU_MODE_KERNEL) { + add_sample_entry(s->eip, s->event); + return 1; + } +@@ -501,9 +527,10 @@ void sync_buffer(int cpu) + unsigned long val; + struct task_struct *new; + unsigned long cookie = 0; +- int in_kernel = 1; ++ int cpu_mode = CPU_MODE_KERNEL; + sync_buffer_state state = sb_buffer_start; + unsigned int i; ++ int domain_switch = 0; + unsigned long available; + unsigned long flags; + struct op_entry entry; +@@ -513,6 +540,11 @@ void sync_buffer(int cpu) + + add_cpu_switch(cpu); + ++ /* We need to assign the first samples in this CPU buffer to the ++ same domain that we were processing at the last sync_buffer */ ++ if (cpu_current_domain[cpu] != COORDINATOR_DOMAIN) ++ add_domain_switch(cpu_current_domain[cpu]); ++ + op_cpu_buffer_reset(cpu); + available = op_cpu_buffer_entries(cpu); + +@@ -521,6 +553,13 @@ void sync_buffer(int cpu) + if (!sample) + break; + ++ if (domain_switch) { ++ cpu_current_domain[cpu] = sample->eip; ++ add_domain_switch(sample->eip); ++ domain_switch = 0; ++ continue; ++ } ++ + if (is_code(sample->eip)) { + flags = sample->event; + if (flags & TRACE_BEGIN) { +@@ -529,10 +568,10 @@ void sync_buffer(int cpu) + } + if (flags & KERNEL_CTX_SWITCH) { + /* kernel/userspace switch */ +- in_kernel = flags & IS_KERNEL; ++ cpu_mode = flags & CPU_MODE_MASK; + if (state == sb_buffer_start) + state = sb_sample_start; +- add_kernel_ctx_switch(flags & IS_KERNEL); ++ add_cpu_mode_switch(cpu_mode); + } + if (flags & USER_CTX_SWITCH + && op_cpu_buffer_get_data(&entry, &val)) { +@@ -545,16 +584,23 @@ void sync_buffer(int cpu) + cookie = get_exec_dcookie(mm); + add_user_ctx_switch(new, cookie); + } ++ if (flags & DOMAIN_SWITCH) ++ domain_switch = 1; + if (op_cpu_buffer_get_size(&entry)) + add_data(&entry, mm); + continue; + } + ++ if (cpu_current_domain[cpu] != COORDINATOR_DOMAIN) { ++ add_sample_entry(sample->eip, sample->event); ++ continue; ++ } ++ + if (state < sb_bt_start) + /* ignore sample */ + continue; + +- if (add_sample(mm, sample, in_kernel)) ++ if (add_sample(mm, sample, cpu_mode)) + continue; + + /* ignore backtraces if failed to add a sample */ +@@ -565,6 +611,10 @@ void sync_buffer(int cpu) + } + release_mm(mm); + ++ /* We reset domain to COORDINATOR at each CPU switch */ ++ if (cpu_current_domain[cpu] != COORDINATOR_DOMAIN) ++ add_domain_switch(COORDINATOR_DOMAIN); ++ + mark_done(cpu); + + mutex_unlock(&buffer_mutex); +--- sle11sp1-2010-03-22.orig/drivers/oprofile/cpu_buffer.c 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/oprofile/cpu_buffer.c 2009-12-04 10:44:41.000000000 +0100 +@@ -8,6 +8,10 @@ + * @author Barry Kasindorf + * @author Robert Richter + * ++ * Modified by Aravind Menon for Xen ++ * These modifications are: ++ * Copyright (C) 2005 Hewlett-Packard Co. ++ * + * Each CPU has a local buffer that stores PC value/event + * pairs. We also log context switches when we notice them. + * Eventually each CPU's buffer is processed into the global +@@ -54,6 +58,8 @@ static void wq_sync_buffer(struct work_s + #define DEFAULT_TIMER_EXPIRE (HZ / 10) + static int work_enabled; + ++static int32_t current_domain = COORDINATOR_DOMAIN; ++ + unsigned long oprofile_get_cpu_buffer_size(void) + { + return oprofile_cpu_buffer_size; +@@ -98,7 +104,7 @@ int alloc_cpu_buffers(void) + struct oprofile_cpu_buffer *b = &per_cpu(cpu_buffer, i); + + b->last_task = NULL; +- b->last_is_kernel = -1; ++ b->last_cpu_mode = -1; + b->tracing = 0; + b->buffer_size = buffer_size; + b->sample_received = 0; +@@ -216,7 +222,7 @@ unsigned long op_cpu_buffer_entries(int + + static int + op_add_code(struct oprofile_cpu_buffer *cpu_buf, unsigned long backtrace, +- int is_kernel, struct task_struct *task) ++ int cpu_mode, struct task_struct *task) + { + struct op_entry entry; + struct op_sample *sample; +@@ -229,16 +235,15 @@ op_add_code(struct oprofile_cpu_buffer * + flags |= TRACE_BEGIN; + + /* notice a switch from user->kernel or vice versa */ +- is_kernel = !!is_kernel; +- if (cpu_buf->last_is_kernel != is_kernel) { +- cpu_buf->last_is_kernel = is_kernel; +- flags |= KERNEL_CTX_SWITCH; +- if (is_kernel) +- flags |= IS_KERNEL; ++ if (cpu_buf->last_cpu_mode != cpu_mode) { ++ cpu_buf->last_cpu_mode = cpu_mode; ++ flags |= KERNEL_CTX_SWITCH | cpu_mode; + } + + /* notice a task switch */ +- if (cpu_buf->last_task != task) { ++ /* if not processing other domain samples */ ++ if (cpu_buf->last_task != task && ++ current_domain == COORDINATOR_DOMAIN) { + cpu_buf->last_task = task; + flags |= USER_CTX_SWITCH; + } +@@ -287,14 +292,14 @@ op_add_sample(struct oprofile_cpu_buffer + /* + * This must be safe from any context. + * +- * is_kernel is needed because on some architectures you cannot ++ * cpu_mode is needed because on some architectures you cannot + * tell if you are in kernel or user space simply by looking at +- * pc. We tag this in the buffer by generating kernel enter/exit +- * events whenever is_kernel changes ++ * pc. We tag this in the buffer by generating kernel/user (and ++ * xen) enter events whenever cpu_mode changes + */ + static int + log_sample(struct oprofile_cpu_buffer *cpu_buf, unsigned long pc, +- unsigned long backtrace, int is_kernel, unsigned long event) ++ unsigned long backtrace, int cpu_mode, unsigned long event) + { + cpu_buf->sample_received++; + +@@ -303,7 +308,7 @@ log_sample(struct oprofile_cpu_buffer *c + return 0; + } + +- if (op_add_code(cpu_buf, backtrace, is_kernel, current)) ++ if (op_add_code(cpu_buf, backtrace, cpu_mode, current)) + goto fail; + + if (op_add_sample(cpu_buf, pc, event)) +@@ -458,6 +463,25 @@ fail: + return; + } + ++int oprofile_add_domain_switch(int32_t domain_id) ++{ ++ struct oprofile_cpu_buffer * cpu_buf = &cpu_buffer[smp_processor_id()]; ++ ++ /* should have space for switching into and out of domain ++ (2 slots each) plus one sample and one cpu mode switch */ ++ if (((nr_available_slots(cpu_buf) < 6) && ++ (domain_id != COORDINATOR_DOMAIN)) || ++ (nr_available_slots(cpu_buf) < 2)) ++ return 0; ++ ++ add_code(cpu_buf, DOMAIN_SWITCH); ++ add_sample(cpu_buf, domain_id, 0); ++ ++ current_domain = domain_id; ++ ++ return 1; ++} ++ + /* + * This serves to avoid cpu buffer overflow, and makes sure + * the task mortuary progresses +--- sle11sp1-2010-03-22.orig/drivers/oprofile/cpu_buffer.h 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/oprofile/cpu_buffer.h 2009-12-04 10:44:41.000000000 +0100 +@@ -40,7 +40,7 @@ struct op_entry; + struct oprofile_cpu_buffer { + unsigned long buffer_size; + struct task_struct *last_task; +- int last_is_kernel; ++ int last_cpu_mode; + int tracing; + unsigned long sample_received; + unsigned long sample_lost_overflow; +@@ -62,7 +62,7 @@ static inline void op_cpu_buffer_reset(i + { + struct oprofile_cpu_buffer *cpu_buf = &per_cpu(cpu_buffer, cpu); + +- cpu_buf->last_is_kernel = -1; ++ cpu_buf->last_cpu_mode = -1; + cpu_buf->last_task = NULL; + } + +@@ -112,9 +112,13 @@ int op_cpu_buffer_get_data(struct op_ent + } + + /* extra data flags */ +-#define KERNEL_CTX_SWITCH (1UL << 0) +-#define IS_KERNEL (1UL << 1) ++#define CPU_MODE_USER 0 ++#define CPU_MODE_KERNEL 1 ++#define CPU_MODE_XEN 2 ++#define CPU_MODE_MASK 3 + #define TRACE_BEGIN (1UL << 2) + #define USER_CTX_SWITCH (1UL << 3) ++#define KERNEL_CTX_SWITCH (1UL << 4) ++#define DOMAIN_SWITCH (1UL << 5) + + #endif /* OPROFILE_CPU_BUFFER_H */ +--- sle11sp1-2010-03-22.orig/drivers/oprofile/event_buffer.h 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/oprofile/event_buffer.h 2009-12-04 10:44:41.000000000 +0100 +@@ -30,6 +30,9 @@ void wake_up_buffer_waiter(void); + #define INVALID_COOKIE ~0UL + #define NO_COOKIE 0UL + ++/* Constant used to refer to coordinator domain (Xen) */ ++#define COORDINATOR_DOMAIN -1 ++ + extern const struct file_operations event_buffer_fops; + + /* mutex between sync_cpu_buffers() and the +--- sle11sp1-2010-03-22.orig/drivers/oprofile/oprof.c 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/oprofile/oprof.c 2009-12-04 10:44:41.000000000 +0100 +@@ -5,6 +5,10 @@ + * @remark Read the file COPYING + * + * @author John Levon ++ * ++ * Modified by Aravind Menon for Xen ++ * These modifications are: ++ * Copyright (C) 2005 Hewlett-Packard Co. + */ + + #include +@@ -35,6 +39,32 @@ static DEFINE_MUTEX(start_mutex); + */ + static int timer = 0; + ++int oprofile_set_active(int active_domains[], unsigned int adomains) ++{ ++ int err; ++ ++ if (!oprofile_ops.set_active) ++ return -EINVAL; ++ ++ mutex_lock(&start_mutex); ++ err = oprofile_ops.set_active(active_domains, adomains); ++ mutex_unlock(&start_mutex); ++ return err; ++} ++ ++int oprofile_set_passive(int passive_domains[], unsigned int pdomains) ++{ ++ int err; ++ ++ if (!oprofile_ops.set_passive) ++ return -EINVAL; ++ ++ mutex_lock(&start_mutex); ++ err = oprofile_ops.set_passive(passive_domains, pdomains); ++ mutex_unlock(&start_mutex); ++ return err; ++} ++ + int oprofile_setup(void) + { + int err; +--- sle11sp1-2010-03-22.orig/drivers/oprofile/oprof.h 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/oprofile/oprof.h 2009-12-04 10:44:41.000000000 +0100 +@@ -39,4 +39,7 @@ void oprofile_timer_init(struct oprofile + int oprofile_set_backtrace(unsigned long depth); + int oprofile_set_timeout(unsigned long time); + ++int oprofile_set_active(int active_domains[], unsigned int adomains); ++int oprofile_set_passive(int passive_domains[], unsigned int pdomains); ++ + #endif /* OPROF_H */ +--- sle11sp1-2010-03-22.orig/drivers/oprofile/oprofile_files.c 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/drivers/oprofile/oprofile_files.c 2009-12-04 10:44:41.000000000 +0100 +@@ -5,11 +5,17 @@ + * @remark Read the file COPYING + * + * @author John Levon ++ * ++ * Modified by Aravind Menon for Xen ++ * These modifications are: ++ * Copyright (C) 2005 Hewlett-Packard Co. + */ + + #include + #include + #include ++#include ++#include + + #include "event_buffer.h" + #include "oprofile_stats.h" +@@ -165,6 +171,195 @@ static const struct file_operations dump + .write = dump_write, + }; + ++#define TMPBUFSIZE 512 ++ ++static unsigned int adomains = 0; ++static int active_domains[MAX_OPROF_DOMAINS + 1]; ++static DEFINE_MUTEX(adom_mutex); ++ ++static ssize_t adomain_write(struct file * file, char const __user * buf, ++ size_t count, loff_t * offset) ++{ ++ char *tmpbuf; ++ char *startp, *endp; ++ int i; ++ unsigned long val; ++ ssize_t retval = count; ++ ++ if (*offset) ++ return -EINVAL; ++ if (count > TMPBUFSIZE - 1) ++ return -EINVAL; ++ ++ if (!(tmpbuf = kmalloc(TMPBUFSIZE, GFP_KERNEL))) ++ return -ENOMEM; ++ ++ if (copy_from_user(tmpbuf, buf, count)) { ++ kfree(tmpbuf); ++ return -EFAULT; ++ } ++ tmpbuf[count] = 0; ++ ++ mutex_lock(&adom_mutex); ++ ++ startp = tmpbuf; ++ /* Parse one more than MAX_OPROF_DOMAINS, for easy error checking */ ++ for (i = 0; i <= MAX_OPROF_DOMAINS; i++) { ++ val = simple_strtoul(startp, &endp, 0); ++ if (endp == startp) ++ break; ++ while (ispunct(*endp) || isspace(*endp)) ++ endp++; ++ active_domains[i] = val; ++ if (active_domains[i] != val) ++ /* Overflow, force error below */ ++ i = MAX_OPROF_DOMAINS + 1; ++ startp = endp; ++ } ++ /* Force error on trailing junk */ ++ adomains = *startp ? MAX_OPROF_DOMAINS + 1 : i; ++ ++ kfree(tmpbuf); ++ ++ if (adomains > MAX_OPROF_DOMAINS ++ || oprofile_set_active(active_domains, adomains)) { ++ adomains = 0; ++ retval = -EINVAL; ++ } ++ ++ mutex_unlock(&adom_mutex); ++ return retval; ++} ++ ++static ssize_t adomain_read(struct file * file, char __user * buf, ++ size_t count, loff_t * offset) ++{ ++ char * tmpbuf; ++ size_t len; ++ int i; ++ ssize_t retval; ++ ++ if (!(tmpbuf = kmalloc(TMPBUFSIZE, GFP_KERNEL))) ++ return -ENOMEM; ++ ++ mutex_lock(&adom_mutex); ++ ++ len = 0; ++ for (i = 0; i < adomains; i++) ++ len += snprintf(tmpbuf + len, ++ len < TMPBUFSIZE ? TMPBUFSIZE - len : 0, ++ "%u ", active_domains[i]); ++ WARN_ON(len > TMPBUFSIZE); ++ if (len != 0 && len <= TMPBUFSIZE) ++ tmpbuf[len-1] = '\n'; ++ ++ mutex_unlock(&adom_mutex); ++ ++ retval = simple_read_from_buffer(buf, count, offset, tmpbuf, len); ++ ++ kfree(tmpbuf); ++ return retval; ++} ++ ++ ++static const struct file_operations active_domain_ops = { ++ .read = adomain_read, ++ .write = adomain_write, ++}; ++ ++static unsigned int pdomains = 0; ++static int passive_domains[MAX_OPROF_DOMAINS]; ++static DEFINE_MUTEX(pdom_mutex); ++ ++static ssize_t pdomain_write(struct file * file, char const __user * buf, ++ size_t count, loff_t * offset) ++{ ++ char *tmpbuf; ++ char *startp, *endp; ++ int i; ++ unsigned long val; ++ ssize_t retval = count; ++ ++ if (*offset) ++ return -EINVAL; ++ if (count > TMPBUFSIZE - 1) ++ return -EINVAL; ++ ++ if (!(tmpbuf = kmalloc(TMPBUFSIZE, GFP_KERNEL))) ++ return -ENOMEM; ++ ++ if (copy_from_user(tmpbuf, buf, count)) { ++ kfree(tmpbuf); ++ return -EFAULT; ++ } ++ tmpbuf[count] = 0; ++ ++ mutex_lock(&pdom_mutex); ++ ++ startp = tmpbuf; ++ /* Parse one more than MAX_OPROF_DOMAINS, for easy error checking */ ++ for (i = 0; i <= MAX_OPROF_DOMAINS; i++) { ++ val = simple_strtoul(startp, &endp, 0); ++ if (endp == startp) ++ break; ++ while (ispunct(*endp) || isspace(*endp)) ++ endp++; ++ passive_domains[i] = val; ++ if (passive_domains[i] != val) ++ /* Overflow, force error below */ ++ i = MAX_OPROF_DOMAINS + 1; ++ startp = endp; ++ } ++ /* Force error on trailing junk */ ++ pdomains = *startp ? MAX_OPROF_DOMAINS + 1 : i; ++ ++ kfree(tmpbuf); ++ ++ if (pdomains > MAX_OPROF_DOMAINS ++ || oprofile_set_passive(passive_domains, pdomains)) { ++ pdomains = 0; ++ retval = -EINVAL; ++ } ++ ++ mutex_unlock(&pdom_mutex); ++ return retval; ++} ++ ++static ssize_t pdomain_read(struct file * file, char __user * buf, ++ size_t count, loff_t * offset) ++{ ++ char * tmpbuf; ++ size_t len; ++ int i; ++ ssize_t retval; ++ ++ if (!(tmpbuf = kmalloc(TMPBUFSIZE, GFP_KERNEL))) ++ return -ENOMEM; ++ ++ mutex_lock(&pdom_mutex); ++ ++ len = 0; ++ for (i = 0; i < pdomains; i++) ++ len += snprintf(tmpbuf + len, ++ len < TMPBUFSIZE ? TMPBUFSIZE - len : 0, ++ "%u ", passive_domains[i]); ++ WARN_ON(len > TMPBUFSIZE); ++ if (len != 0 && len <= TMPBUFSIZE) ++ tmpbuf[len-1] = '\n'; ++ ++ mutex_unlock(&pdom_mutex); ++ ++ retval = simple_read_from_buffer(buf, count, offset, tmpbuf, len); ++ ++ kfree(tmpbuf); ++ return retval; ++} ++ ++static const struct file_operations passive_domain_ops = { ++ .read = pdomain_read, ++ .write = pdomain_write, ++}; ++ + void oprofile_create_files(struct super_block *sb, struct dentry *root) + { + /* reinitialize default values */ +@@ -175,6 +370,8 @@ void oprofile_create_files(struct super_ + + oprofilefs_create_file(sb, root, "enable", &enable_fops); + oprofilefs_create_file_perm(sb, root, "dump", &dump_fops, 0666); ++ oprofilefs_create_file(sb, root, "active_domains", &active_domain_ops); ++ oprofilefs_create_file(sb, root, "passive_domains", &passive_domain_ops); + oprofilefs_create_file(sb, root, "buffer", &event_buffer_fops); + oprofilefs_create_ulong(sb, root, "buffer_size", &oprofile_buffer_size); + oprofilefs_create_ulong(sb, root, "buffer_watershed", &oprofile_buffer_watershed); +--- sle11sp1-2010-03-22.orig/fs/aio.c 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/fs/aio.c 2009-12-04 10:44:41.000000000 +0100 +@@ -36,6 +36,11 @@ + #include + #include + ++#ifdef CONFIG_EPOLL ++#include ++#include ++#endif ++ + #if DEBUG > 1 + #define dprintk printk + #else +@@ -992,6 +997,11 @@ put_rq: + if (waitqueue_active(&ctx->wait)) + wake_up(&ctx->wait); + ++#ifdef CONFIG_EPOLL ++ if (ctx->file && waitqueue_active(&ctx->poll_wait)) ++ wake_up(&ctx->poll_wait); ++#endif ++ + spin_unlock_irqrestore(&ctx->ctx_lock, flags); + return ret; + } +@@ -1000,6 +1010,8 @@ EXPORT_SYMBOL(aio_complete); + /* aio_read_evt + * Pull an event off of the ioctx's event ring. Returns the number of + * events fetched (0 or 1 ;-) ++ * If ent parameter is 0, just returns the number of events that would ++ * be fetched. + * FIXME: make this use cmpxchg. + * TODO: make the ringbuffer user mmap()able (requires FIXME). + */ +@@ -1022,13 +1034,18 @@ static int aio_read_evt(struct kioctx *i + + head = ring->head % info->nr; + if (head != ring->tail) { +- struct io_event *evp = aio_ring_event(info, head, KM_USER1); +- *ent = *evp; +- head = (head + 1) % info->nr; +- smp_mb(); /* finish reading the event before updatng the head */ +- ring->head = head; +- ret = 1; +- put_aio_ring_event(evp, KM_USER1); ++ if (ent) { /* event requested */ ++ struct io_event *evp = ++ aio_ring_event(info, head, KM_USER1); ++ *ent = *evp; ++ head = (head + 1) % info->nr; ++ /* finish reading the event before updatng the head */ ++ smp_mb(); ++ ring->head = head; ++ ret = 1; ++ put_aio_ring_event(evp, KM_USER1); ++ } else /* only need to know availability */ ++ ret = 1; + } + spin_unlock(&info->ring_lock); + +@@ -1213,6 +1230,13 @@ static void io_destroy(struct kioctx *io + + aio_cancel_all(ioctx); + wait_for_all_aios(ioctx); ++#ifdef CONFIG_EPOLL ++ /* forget the poll file, but it's up to the user to close it */ ++ if (ioctx->file) { ++ ioctx->file->private_data = 0; ++ ioctx->file = 0; ++ } ++#endif + + /* + * Wake up any waiters. The setting of ctx->dead must be seen +@@ -1223,6 +1247,67 @@ static void io_destroy(struct kioctx *io + put_ioctx(ioctx); /* once for the lookup */ + } + ++#ifdef CONFIG_EPOLL ++ ++static int aio_queue_fd_close(struct inode *inode, struct file *file) ++{ ++ struct kioctx *ioctx = file->private_data; ++ if (ioctx) { ++ file->private_data = 0; ++ spin_lock_irq(&ioctx->ctx_lock); ++ ioctx->file = 0; ++ spin_unlock_irq(&ioctx->ctx_lock); ++ } ++ return 0; ++} ++ ++static unsigned int aio_queue_fd_poll(struct file *file, poll_table *wait) ++{ unsigned int pollflags = 0; ++ struct kioctx *ioctx = file->private_data; ++ ++ if (ioctx) { ++ ++ spin_lock_irq(&ioctx->ctx_lock); ++ /* Insert inside our poll wait queue */ ++ poll_wait(file, &ioctx->poll_wait, wait); ++ ++ /* Check our condition */ ++ if (aio_read_evt(ioctx, 0)) ++ pollflags = POLLIN | POLLRDNORM; ++ spin_unlock_irq(&ioctx->ctx_lock); ++ } ++ ++ return pollflags; ++} ++ ++static const struct file_operations aioq_fops = { ++ .release = aio_queue_fd_close, ++ .poll = aio_queue_fd_poll ++}; ++ ++/* make_aio_fd: ++ * Create a file descriptor that can be used to poll the event queue. ++ * Based and piggybacked on the excellent epoll code. ++ */ ++ ++static int make_aio_fd(struct kioctx *ioctx) ++{ ++ int error, fd; ++ struct inode *inode; ++ struct file *file; ++ ++ error = ep_getfd(&fd, &inode, &file, NULL, &aioq_fops); ++ if (error) ++ return error; ++ ++ /* associate the file with the IO context */ ++ file->private_data = ioctx; ++ ioctx->file = file; ++ init_waitqueue_head(&ioctx->poll_wait); ++ return fd; ++} ++#endif ++ + /* sys_io_setup: + * Create an aio_context capable of receiving at least nr_events. + * ctxp must not point to an aio_context that already exists, and +@@ -1235,18 +1320,30 @@ static void io_destroy(struct kioctx *io + * resources are available. May fail with -EFAULT if an invalid + * pointer is passed for ctxp. Will fail with -ENOSYS if not + * implemented. ++ * ++ * To request a selectable fd, the user context has to be initialized ++ * to 1, instead of 0, and the return value is the fd. ++ * This keeps the system call compatible, since a non-zero value ++ * was not allowed so far. + */ + SYSCALL_DEFINE2(io_setup, unsigned, nr_events, aio_context_t __user *, ctxp) + { + struct kioctx *ioctx = NULL; + unsigned long ctx; + long ret; ++ int make_fd = 0; + + ret = get_user(ctx, ctxp); + if (unlikely(ret)) + goto out; + + ret = -EINVAL; ++#ifdef CONFIG_EPOLL ++ if (ctx == 1) { ++ make_fd = 1; ++ ctx = 0; ++ } ++#endif + if (unlikely(ctx || nr_events == 0)) { + pr_debug("EINVAL: io_setup: ctx %lu nr_events %u\n", + ctx, nr_events); +@@ -1257,8 +1354,12 @@ SYSCALL_DEFINE2(io_setup, unsigned, nr_e + ret = PTR_ERR(ioctx); + if (!IS_ERR(ioctx)) { + ret = put_user(ioctx->user_id, ctxp); +- if (!ret) +- return 0; ++#ifdef CONFIG_EPOLL ++ if (make_fd && ret >= 0) ++ ret = make_aio_fd(ioctx); ++#endif ++ if (ret >= 0) ++ return ret; + + get_ioctx(ioctx); /* io_destroy() expects us to hold a ref */ + io_destroy(ioctx); +--- sle11sp1-2010-03-22.orig/fs/compat_ioctl.c 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/fs/compat_ioctl.c 2010-03-05 10:13:02.000000000 +0100 +@@ -115,6 +115,13 @@ + #include + #endif + ++#ifdef CONFIG_XEN ++#include ++#include ++#include ++#include ++#endif ++ + static int do_ioctl32_pointer(unsigned int fd, unsigned int cmd, + unsigned long arg, struct file *f) + { +@@ -2733,6 +2740,19 @@ IGNORE_IOCTL(FBIOGETCMAP32) + IGNORE_IOCTL(FBIOSCURSOR32) + IGNORE_IOCTL(FBIOGCURSOR32) + #endif ++ ++#ifdef CONFIG_XEN ++HANDLE_IOCTL(IOCTL_PRIVCMD_MMAP_32, privcmd_ioctl_32) ++HANDLE_IOCTL(IOCTL_PRIVCMD_MMAPBATCH_32, privcmd_ioctl_32) ++HANDLE_IOCTL(IOCTL_PRIVCMD_MMAPBATCH_V2_32, privcmd_ioctl_32) ++COMPATIBLE_IOCTL(IOCTL_PRIVCMD_HYPERCALL) ++COMPATIBLE_IOCTL(IOCTL_EVTCHN_BIND_VIRQ) ++COMPATIBLE_IOCTL(IOCTL_EVTCHN_BIND_INTERDOMAIN) ++COMPATIBLE_IOCTL(IOCTL_EVTCHN_BIND_UNBOUND_PORT) ++COMPATIBLE_IOCTL(IOCTL_EVTCHN_UNBIND) ++COMPATIBLE_IOCTL(IOCTL_EVTCHN_NOTIFY) ++COMPATIBLE_IOCTL(IOCTL_EVTCHN_RESET) ++#endif + }; + + #define IOCTL_HASHSIZE 256 +--- sle11sp1-2010-03-22.orig/include/acpi/processor.h 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/include/acpi/processor.h 2009-12-04 10:44:41.000000000 +0100 +@@ -17,6 +17,12 @@ + #define ACPI_PROCESSOR_MAX_THROTTLE 250 /* 25% */ + #define ACPI_PROCESSOR_MAX_DUTY_WIDTH 4 + ++#ifdef CONFIG_XEN ++#define NR_ACPI_CPUS (NR_CPUS < 256 ? 256 : NR_CPUS) ++#else ++#define NR_ACPI_CPUS NR_CPUS ++#endif /* CONFIG_XEN */ ++ + #define ACPI_PDC_REVISION_ID 0x1 + + #define ACPI_PSD_REV0_REVISION 0 /* Support for _PSD as in ACPI 3.0 */ +@@ -42,6 +48,17 @@ + + struct acpi_processor_cx; + ++#ifdef CONFIG_PROCESSOR_EXTERNAL_CONTROL ++struct acpi_csd_package { ++ acpi_integer num_entries; ++ acpi_integer revision; ++ acpi_integer domain; ++ acpi_integer coord_type; ++ acpi_integer num_processors; ++ acpi_integer index; ++} __attribute__ ((packed)); ++#endif ++ + struct acpi_power_register { + u8 descriptor; + u16 length; +@@ -74,6 +91,12 @@ struct acpi_processor_cx { + u32 power; + u32 usage; + u64 time; ++#ifdef CONFIG_PROCESSOR_EXTERNAL_CONTROL ++ /* Require raw information for external control logic */ ++ struct acpi_power_register reg; ++ u32 csd_count; ++ struct acpi_csd_package *domain_info; ++#endif + struct acpi_processor_cx_policy promotion; + struct acpi_processor_cx_policy demotion; + char desc[ACPI_CX_DESC_LEN]; +@@ -304,6 +327,9 @@ static inline void acpi_processor_ppc_ex + { + return; + } ++#ifdef CONFIG_PROCESSOR_EXTERNAL_CONTROL ++int acpi_processor_ppc_has_changed(struct acpi_processor *pr); ++#else + static inline int acpi_processor_ppc_has_changed(struct acpi_processor *pr) + { + static unsigned int printout = 1; +@@ -316,6 +342,7 @@ static inline int acpi_processor_ppc_has + } + return 0; + } ++#endif /* CONFIG_PROCESSOR_EXTERNAL_CONTROL */ + #endif /* CONFIG_CPU_FREQ */ + + /* in processor_throttling.c */ +@@ -353,4 +380,120 @@ static inline void acpi_thermal_cpufreq_ + } + #endif + ++/* ++ * Following are interfaces geared to external processor PM control ++ * logic like a VMM ++ */ ++/* Events notified to external control logic */ ++#define PROCESSOR_PM_INIT 1 ++#define PROCESSOR_PM_CHANGE 2 ++#define PROCESSOR_HOTPLUG 3 ++ ++/* Objects for the PM events */ ++#define PM_TYPE_IDLE 0 ++#define PM_TYPE_PERF 1 ++#define PM_TYPE_THR 2 ++#define PM_TYPE_MAX 3 ++ ++/* Processor hotplug events */ ++#define HOTPLUG_TYPE_ADD 0 ++#define HOTPLUG_TYPE_REMOVE 1 ++ ++#ifdef CONFIG_PROCESSOR_EXTERNAL_CONTROL ++struct processor_extcntl_ops { ++ /* Transfer processor PM events to external control logic */ ++ int (*pm_ops[PM_TYPE_MAX])(struct acpi_processor *pr, int event); ++ /* Notify physical processor status to external control logic */ ++ int (*hotplug)(struct acpi_processor *pr, int type); ++}; ++extern const struct processor_extcntl_ops *processor_extcntl_ops; ++ ++static inline int processor_cntl_external(void) ++{ ++ return (processor_extcntl_ops != NULL); ++} ++ ++static inline int processor_pm_external(void) ++{ ++ return processor_cntl_external() && ++ (processor_extcntl_ops->pm_ops[PM_TYPE_IDLE] != NULL); ++} ++ ++static inline int processor_pmperf_external(void) ++{ ++ return processor_cntl_external() && ++ (processor_extcntl_ops->pm_ops[PM_TYPE_PERF] != NULL); ++} ++ ++static inline int processor_pmthr_external(void) ++{ ++ return processor_cntl_external() && ++ (processor_extcntl_ops->pm_ops[PM_TYPE_THR] != NULL); ++} ++ ++extern int processor_notify_external(struct acpi_processor *pr, ++ int event, int type); ++extern void processor_extcntl_init(void); ++extern int processor_extcntl_prepare(struct acpi_processor *pr); ++extern int acpi_processor_get_performance_info(struct acpi_processor *pr); ++extern int acpi_processor_get_psd(struct acpi_processor *pr); ++void arch_acpi_processor_init_extcntl(const struct processor_extcntl_ops **); ++#else ++static inline int processor_cntl_external(void) {return 0;} ++static inline int processor_pm_external(void) {return 0;} ++static inline int processor_pmperf_external(void) {return 0;} ++static inline int processor_pmthr_external(void) {return 0;} ++static inline int processor_notify_external(struct acpi_processor *pr, ++ int event, int type) ++{ ++ return 0; ++} ++static inline void processor_extcntl_init(void) {} ++static inline int processor_extcntl_prepare(struct acpi_processor *pr) ++{ ++ return 0; ++} ++#endif /* CONFIG_PROCESSOR_EXTERNAL_CONTROL */ ++ ++#ifdef CONFIG_XEN ++static inline void xen_convert_pct_reg(struct xen_pct_register *xpct, ++ struct acpi_pct_register *apct) ++{ ++ xpct->descriptor = apct->descriptor; ++ xpct->length = apct->length; ++ xpct->space_id = apct->space_id; ++ xpct->bit_width = apct->bit_width; ++ xpct->bit_offset = apct->bit_offset; ++ xpct->reserved = apct->reserved; ++ xpct->address = apct->address; ++} ++ ++static inline void xen_convert_pss_states(struct xen_processor_px *xpss, ++ struct acpi_processor_px *apss, int state_count) ++{ ++ int i; ++ for(i=0; icore_frequency = apss->core_frequency; ++ xpss->power = apss->power; ++ xpss->transition_latency = apss->transition_latency; ++ xpss->bus_master_latency = apss->bus_master_latency; ++ xpss->control = apss->control; ++ xpss->status = apss->status; ++ xpss++; ++ apss++; ++ } ++} ++ ++static inline void xen_convert_psd_pack(struct xen_psd_package *xpsd, ++ struct acpi_psd_package *apsd) ++{ ++ xpsd->num_entries = apsd->num_entries; ++ xpsd->revision = apsd->revision; ++ xpsd->domain = apsd->domain; ++ xpsd->coord_type = apsd->coord_type; ++ xpsd->num_processors = apsd->num_processors; ++} ++ ++#endif /* CONFIG_XEN */ ++ + #endif +--- sle11sp1-2010-03-22.orig/include/asm-generic/pgtable.h 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/include/asm-generic/pgtable.h 2009-12-04 10:44:41.000000000 +0100 +@@ -99,6 +99,10 @@ static inline void ptep_set_wrprotect(st + } + #endif + ++#ifndef arch_change_pte_range ++#define arch_change_pte_range(mm, pmd, addr, end, newprot) 0 ++#endif ++ + #ifndef __HAVE_ARCH_PTE_SAME + #define pte_same(A,B) (pte_val(A) == pte_val(B)) + #endif +--- sle11sp1-2010-03-22.orig/include/linux/aio.h 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/include/linux/aio.h 2009-12-04 10:44:41.000000000 +0100 +@@ -201,6 +201,12 @@ struct kioctx { + + struct delayed_work wq; + ++#ifdef CONFIG_EPOLL ++ /* poll integration */ ++ wait_queue_head_t poll_wait; ++ struct file *file; ++#endif ++ + struct rcu_head rcu_head; + }; + +--- sle11sp1-2010-03-22.orig/include/linux/highmem.h 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/include/linux/highmem.h 2009-12-04 10:44:41.000000000 +0100 +@@ -130,12 +130,14 @@ alloc_zeroed_user_highpage_movable(struc + return __alloc_zeroed_user_highpage(__GFP_MOVABLE, vma, vaddr); + } + ++#ifndef __HAVE_ARCH_CLEAR_HIGHPAGE + static inline void clear_highpage(struct page *page) + { + void *kaddr = kmap_atomic(page, KM_USER0); + clear_page(kaddr); + kunmap_atomic(kaddr, KM_USER0); + } ++#endif + + static inline void zero_user_segments(struct page *page, + unsigned start1, unsigned end1, +@@ -189,6 +191,8 @@ static inline void copy_user_highpage(st + + #endif + ++#ifndef __HAVE_ARCH_COPY_HIGHPAGE ++ + static inline void copy_highpage(struct page *to, struct page *from) + { + char *vfrom, *vto; +@@ -200,4 +204,6 @@ static inline void copy_highpage(struct + kunmap_atomic(vto, KM_USER1); + } + ++#endif ++ + #endif /* _LINUX_HIGHMEM_H */ +--- sle11sp1-2010-03-22.orig/include/linux/interrupt.h 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/include/linux/interrupt.h 2009-12-04 10:44:41.000000000 +0100 +@@ -317,6 +317,12 @@ static inline int disable_irq_wake(unsig + } + #endif /* CONFIG_GENERIC_HARDIRQS */ + ++#ifdef CONFIG_HAVE_IRQ_IGNORE_UNHANDLED ++int irq_ignore_unhandled(unsigned int irq); ++#else ++#define irq_ignore_unhandled(irq) 0 ++#endif ++ + #ifndef __ARCH_SET_SOFTIRQ_PENDING + #define set_softirq_pending(x) (local_softirq_pending() = (x)) + #define or_softirq_pending(x) (local_softirq_pending() |= (x)) +--- sle11sp1-2010-03-22.orig/include/linux/kexec.h 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/include/linux/kexec.h 2009-12-04 10:44:41.000000000 +0100 +@@ -46,6 +46,13 @@ + KEXEC_CORE_NOTE_NAME_BYTES + \ + KEXEC_CORE_NOTE_DESC_BYTES ) + ++#ifndef KEXEC_ARCH_HAS_PAGE_MACROS ++#define kexec_page_to_pfn(page) page_to_pfn(page) ++#define kexec_pfn_to_page(pfn) pfn_to_page(pfn) ++#define kexec_virt_to_phys(addr) virt_to_phys(addr) ++#define kexec_phys_to_virt(addr) phys_to_virt(addr) ++#endif ++ + /* + * This structure is used to hold the arguments that are used when loading + * kernel binaries. +@@ -112,6 +119,12 @@ struct kimage { + extern void machine_kexec(struct kimage *image); + extern int machine_kexec_prepare(struct kimage *image); + extern void machine_kexec_cleanup(struct kimage *image); ++#ifdef CONFIG_XEN ++extern int xen_machine_kexec_load(struct kimage *image); ++extern void xen_machine_kexec_unload(struct kimage *image); ++extern void xen_machine_kexec_setup_resources(void); ++extern void xen_machine_kexec_register_resources(struct resource *res); ++#endif + extern asmlinkage long sys_kexec_load(unsigned long entry, + unsigned long nr_segments, + struct kexec_segment __user *segments, +--- sle11sp1-2010-03-22.orig/include/linux/mm.h 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/include/linux/mm.h 2009-12-04 10:44:41.000000000 +0100 +@@ -102,7 +102,12 @@ extern unsigned int kobjsize(const void + + #define VM_CAN_NONLINEAR 0x08000000 /* Has ->fault & does nonlinear pages */ + #define VM_MIXEDMAP 0x10000000 /* Can contain "struct page" and pure PFN pages */ ++#ifndef CONFIG_XEN + #define VM_SAO 0x20000000 /* Strong Access Ordering (powerpc) */ ++#else ++#define VM_SAO 0 ++#define VM_FOREIGN 0x20000000 /* Has pages belonging to another VM */ ++#endif + #define VM_PFN_AT_MMAP 0x40000000 /* PFNMAP vma that is fully mapped at mmap time */ + #define VM_MERGEABLE 0x80000000 /* KSM may merge identical pages */ + +@@ -127,6 +132,12 @@ extern unsigned int kobjsize(const void + */ + #define VM_SPECIAL (VM_IO | VM_DONTEXPAND | VM_RESERVED | VM_PFNMAP) + ++#ifdef CONFIG_XEN ++struct vm_foreign_map { ++ struct page **map; ++}; ++#endif ++ + /* + * mapping from the currently active vm_flags protection bits (the + * low four bits) to a page protection mask.. +@@ -198,6 +209,15 @@ struct vm_operations_struct { + */ + int (*access)(struct vm_area_struct *vma, unsigned long addr, + void *buf, int len, int write); ++ ++ /* Area-specific function for clearing the PTE at @ptep. Returns the ++ * original value of @ptep. */ ++ pte_t (*zap_pte)(struct vm_area_struct *vma, ++ unsigned long addr, pte_t *ptep, int is_fullmm); ++ ++ /* called before close() to indicate no more pages should be mapped */ ++ void (*unmap)(struct vm_area_struct *area); ++ + #ifdef CONFIG_NUMA + /* + * set_policy() op must add a reference to any non-NULL @new mempolicy +--- sle11sp1-2010-03-22.orig/include/linux/oprofile.h 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/include/linux/oprofile.h 2009-12-04 10:44:41.000000000 +0100 +@@ -16,6 +16,8 @@ + #include + #include + #include ++ ++#include + + /* Each escaped entry is prefixed by ESCAPE_CODE + * then one of the following codes, then the +@@ -28,14 +30,18 @@ + #define CPU_SWITCH_CODE 2 + #define COOKIE_SWITCH_CODE 3 + #define KERNEL_ENTER_SWITCH_CODE 4 +-#define KERNEL_EXIT_SWITCH_CODE 5 ++#define USER_ENTER_SWITCH_CODE 5 + #define MODULE_LOADED_CODE 6 + #define CTX_TGID_CODE 7 + #define TRACE_BEGIN_CODE 8 + #define TRACE_END_CODE 9 + #define XEN_ENTER_SWITCH_CODE 10 ++#ifndef CONFIG_XEN + #define SPU_PROFILING_CODE 11 + #define SPU_CTX_SWITCH_CODE 12 ++#else ++#define DOMAIN_SWITCH_CODE 11 ++#endif + #define IBS_FETCH_CODE 13 + #define IBS_OP_CODE 14 + +@@ -49,6 +55,11 @@ struct oprofile_operations { + /* create any necessary configuration files in the oprofile fs. + * Optional. */ + int (*create_files)(struct super_block * sb, struct dentry * root); ++ /* setup active domains with Xen */ ++ int (*set_active)(int *active_domains, unsigned int adomains); ++ /* setup passive domains with Xen */ ++ int (*set_passive)(int *passive_domains, unsigned int pdomains); ++ + /* Do any necessary interrupt setup. Optional. */ + int (*setup)(void); + /* Do any necessary interrupt shutdown. Optional. */ +@@ -110,6 +121,9 @@ void oprofile_add_pc(unsigned long pc, i + /* add a backtrace entry, to be called from the ->backtrace callback */ + void oprofile_add_trace(unsigned long eip); + ++/* add a domain switch entry */ ++int oprofile_add_domain_switch(int32_t domain_id); ++ + + /** + * Create a file of the given name as a child of the given root, with +--- sle11sp1-2010-03-22.orig/include/linux/page-flags.h 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/include/linux/page-flags.h 2010-02-17 14:45:18.000000000 +0100 +@@ -110,6 +110,11 @@ enum pageflags { + #ifdef CONFIG_MEMORY_FAILURE + PG_hwpoison, /* hardware poisoned page. Don't touch */ + #endif ++#ifdef CONFIG_XEN ++ PG_foreign, /* Page is owned by foreign allocator. */ ++ PG_netback, /* Page is owned by netback */ ++ PG_blkback, /* Page is owned by blkback */ ++#endif + __NR_PAGEFLAGS, + + /* Filesystems */ +@@ -341,6 +346,27 @@ static inline void SetPageUptodate(struc + + CLEARPAGEFLAG(Uptodate, uptodate) + ++#define PageForeign(page) test_bit(PG_foreign, &(page)->flags) ++#define SetPageForeign(_page, dtor) do { \ ++ set_bit(PG_foreign, &(_page)->flags); \ ++ BUG_ON((dtor) == (void (*)(struct page *, unsigned int))0); \ ++ (_page)->index = (long)(dtor); \ ++} while (0) ++#define ClearPageForeign(page) do { \ ++ clear_bit(PG_foreign, &(page)->flags); \ ++ (page)->index = 0; \ ++} while (0) ++#define PageForeignDestructor(_page, order) \ ++ ((void (*)(struct page *, unsigned int))(_page)->index)(_page, order) ++ ++#define PageNetback(page) test_bit(PG_netback, &(page)->flags) ++#define SetPageNetback(page) set_bit(PG_netback, &(page)->flags) ++#define ClearPageNetback(page) clear_bit(PG_netback, &(page)->flags) ++ ++#define PageBlkback(page) test_bit(PG_blkback, &(page)->flags) ++#define SetPageBlkback(page) set_bit(PG_blkback, &(page)->flags) ++#define ClearPageBlkback(page) clear_bit(PG_blkback, &(page)->flags) ++ + extern void cancel_dirty_page(struct page *page, unsigned int account_size); + + int test_clear_page_writeback(struct page *page); +@@ -417,6 +443,14 @@ PAGEFLAG_FALSE(MemError) + #define __PG_MLOCKED 0 + #endif + ++#if !defined(CONFIG_XEN) ++# define __PG_XEN 0 ++#elif defined(CONFIG_X86) ++# define __PG_XEN ((1 << PG_pinned) | (1 << PG_foreign)) ++#else ++# define __PG_XEN (1 << PG_foreign) ++#endif ++ + /* + * Flags checked when a page is freed. Pages being freed should not have + * these flags set. It they are, there is a problem. +@@ -426,7 +460,8 @@ PAGEFLAG_FALSE(MemError) + 1 << PG_private | 1 << PG_private_2 | \ + 1 << PG_buddy | 1 << PG_writeback | 1 << PG_reserved | \ + 1 << PG_slab | 1 << PG_swapcache | 1 << PG_active | \ +- 1 << PG_unevictable | __PG_MLOCKED | __PG_HWPOISON) ++ 1 << PG_unevictable | __PG_MLOCKED | __PG_HWPOISON | \ ++ __PG_XEN ) + + /* + * Flags checked when a page is prepped for return by the page allocator. +--- sle11sp1-2010-03-22.orig/include/linux/pci.h 2010-03-22 12:11:20.000000000 +0100 ++++ sle11sp1-2010-03-22/include/linux/pci.h 2010-03-11 09:12:52.000000000 +0100 +@@ -912,6 +912,11 @@ static inline int pci_msi_enabled(void) + { + return 0; + } ++ ++#ifdef CONFIG_XEN ++#define register_msi_get_owner(func) 0 ++#define unregister_msi_get_owner(func) 0 ++#endif + #else + extern int pci_enable_msi_block(struct pci_dev *dev, unsigned int nvec); + extern void pci_msi_shutdown(struct pci_dev *dev); +@@ -924,6 +929,10 @@ extern void pci_disable_msix(struct pci_ + extern void msi_remove_pci_irq_vectors(struct pci_dev *dev); + extern void pci_restore_msi_state(struct pci_dev *dev); + extern int pci_msi_enabled(void); ++#ifdef CONFIG_XEN ++extern int register_msi_get_owner(int (*func)(struct pci_dev *dev)); ++extern int unregister_msi_get_owner(int (*func)(struct pci_dev *dev)); ++#endif + #endif + + #ifndef CONFIG_PCIEASPM +--- sle11sp1-2010-03-22.orig/include/linux/skbuff.h 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/include/linux/skbuff.h 2009-12-07 12:13:58.000000000 +0100 +@@ -278,6 +278,8 @@ typedef unsigned char *sk_buff_data_t; + * @local_df: allow local fragmentation + * @cloned: Head may be cloned (check refcnt to be sure) + * @nohdr: Payload reference only, must not modify header ++ * @proto_data_valid: Protocol data validated since arriving at localhost ++ * @proto_csum_blank: Protocol csum must be added before leaving localhost + * @pkt_type: Packet class + * @fclone: skbuff clone status + * @ip_summed: Driver fed us an IP checksum +@@ -382,9 +384,13 @@ struct sk_buff { + #ifdef CONFIG_NETVM + __u8 emergency:1; + #endif ++#ifdef CONFIG_XEN ++ __u8 proto_data_valid:1, ++ proto_csum_blank:1; ++#endif + kmemcheck_bitfield_end(flags2); + +- /* 0/14 bit hole */ ++ /* 0/9...15 bit hole */ + + #ifdef CONFIG_NET_DMA + dma_cookie_t dma_cookie; +--- sle11sp1-2010-03-22.orig/include/linux/vermagic.h 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/include/linux/vermagic.h 2009-12-04 10:44:41.000000000 +0100 +@@ -22,6 +22,11 @@ + #else + #define MODULE_VERMAGIC_MODVERSIONS "" + #endif ++#ifdef CONFIG_XEN ++#define MODULE_VERMAGIC_XEN "Xen " ++#else ++#define MODULE_VERMAGIC_XEN ++#endif + #ifndef MODULE_ARCH_VERMAGIC + #define MODULE_ARCH_VERMAGIC "" + #endif +@@ -30,5 +35,5 @@ + UTS_RELEASE " " \ + MODULE_VERMAGIC_SMP MODULE_VERMAGIC_PREEMPT \ + MODULE_VERMAGIC_MODULE_UNLOAD MODULE_VERMAGIC_MODVERSIONS \ +- MODULE_ARCH_VERMAGIC ++ MODULE_VERMAGIC_XEN MODULE_ARCH_VERMAGIC + +--- sle11sp1-2010-03-22.orig/kernel/irq/spurious.c 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/kernel/irq/spurious.c 2009-12-04 10:44:41.000000000 +0100 +@@ -245,7 +245,7 @@ void note_interrupt(unsigned int irq, st + */ + if (time_after(jiffies, desc->last_unhandled + HZ/10)) + desc->irqs_unhandled = 1; +- else ++ else if (!irq_ignore_unhandled(irq)) + desc->irqs_unhandled++; + desc->last_unhandled = jiffies; + if (unlikely(action_ret != IRQ_NONE)) +--- sle11sp1-2010-03-22.orig/kernel/kexec.c 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/kernel/kexec.c 2009-12-04 10:44:41.000000000 +0100 +@@ -360,13 +360,26 @@ static int kimage_is_destination_range(s + return 0; + } + +-static struct page *kimage_alloc_pages(gfp_t gfp_mask, unsigned int order) ++static struct page *kimage_alloc_pages(gfp_t gfp_mask, unsigned int order, unsigned long limit) + { + struct page *pages; + + pages = alloc_pages(gfp_mask, order); + if (pages) { + unsigned int count, i; ++#ifdef CONFIG_XEN ++ int address_bits; ++ ++ if (limit == ~0UL) ++ address_bits = BITS_PER_LONG; ++ else ++ address_bits = long_log2(limit); ++ ++ if (xen_limit_pages_to_max_mfn(pages, order, address_bits) < 0) { ++ __free_pages(pages, order); ++ return NULL; ++ } ++#endif + pages->mapping = NULL; + set_page_private(pages, order); + count = 1 << order; +@@ -430,10 +443,10 @@ static struct page *kimage_alloc_normal_ + do { + unsigned long pfn, epfn, addr, eaddr; + +- pages = kimage_alloc_pages(GFP_KERNEL, order); ++ pages = kimage_alloc_pages(GFP_KERNEL, order, KEXEC_CONTROL_MEMORY_LIMIT); + if (!pages) + break; +- pfn = page_to_pfn(pages); ++ pfn = kexec_page_to_pfn(pages); + epfn = pfn + count; + addr = pfn << PAGE_SHIFT; + eaddr = epfn << PAGE_SHIFT; +@@ -467,6 +480,7 @@ static struct page *kimage_alloc_normal_ + return pages; + } + ++#ifndef CONFIG_XEN + static struct page *kimage_alloc_crash_control_pages(struct kimage *image, + unsigned int order) + { +@@ -520,7 +534,7 @@ static struct page *kimage_alloc_crash_c + } + /* If I don't overlap any segments I have found my hole! */ + if (i == image->nr_segments) { +- pages = pfn_to_page(hole_start >> PAGE_SHIFT); ++ pages = kexec_pfn_to_page(hole_start >> PAGE_SHIFT); + break; + } + } +@@ -547,6 +561,13 @@ struct page *kimage_alloc_control_pages( + + return pages; + } ++#else /* !CONFIG_XEN */ ++struct page *kimage_alloc_control_pages(struct kimage *image, ++ unsigned int order) ++{ ++ return kimage_alloc_normal_control_pages(image, order); ++} ++#endif + + static int kimage_add_entry(struct kimage *image, kimage_entry_t entry) + { +@@ -562,7 +583,7 @@ static int kimage_add_entry(struct kimag + return -ENOMEM; + + ind_page = page_address(page); +- *image->entry = virt_to_phys(ind_page) | IND_INDIRECTION; ++ *image->entry = kexec_virt_to_phys(ind_page) | IND_INDIRECTION; + image->entry = ind_page; + image->last_entry = ind_page + + ((PAGE_SIZE/sizeof(kimage_entry_t)) - 1); +@@ -621,13 +642,13 @@ static void kimage_terminate(struct kima + #define for_each_kimage_entry(image, ptr, entry) \ + for (ptr = &image->head; (entry = *ptr) && !(entry & IND_DONE); \ + ptr = (entry & IND_INDIRECTION)? \ +- phys_to_virt((entry & PAGE_MASK)): ptr +1) ++ kexec_phys_to_virt((entry & PAGE_MASK)): ptr +1) + + static void kimage_free_entry(kimage_entry_t entry) + { + struct page *page; + +- page = pfn_to_page(entry >> PAGE_SHIFT); ++ page = kexec_pfn_to_page(entry >> PAGE_SHIFT); + kimage_free_pages(page); + } + +@@ -639,6 +660,10 @@ static void kimage_free(struct kimage *i + if (!image) + return; + ++#ifdef CONFIG_XEN ++ xen_machine_kexec_unload(image); ++#endif ++ + kimage_free_extra_pages(image); + for_each_kimage_entry(image, ptr, entry) { + if (entry & IND_INDIRECTION) { +@@ -714,7 +739,7 @@ static struct page *kimage_alloc_page(st + * have a match. + */ + list_for_each_entry(page, &image->dest_pages, lru) { +- addr = page_to_pfn(page) << PAGE_SHIFT; ++ addr = kexec_page_to_pfn(page) << PAGE_SHIFT; + if (addr == destination) { + list_del(&page->lru); + return page; +@@ -725,16 +750,16 @@ static struct page *kimage_alloc_page(st + kimage_entry_t *old; + + /* Allocate a page, if we run out of memory give up */ +- page = kimage_alloc_pages(gfp_mask, 0); ++ page = kimage_alloc_pages(gfp_mask, 0, KEXEC_SOURCE_MEMORY_LIMIT); + if (!page) + return NULL; + /* If the page cannot be used file it away */ +- if (page_to_pfn(page) > ++ if (kexec_page_to_pfn(page) > + (KEXEC_SOURCE_MEMORY_LIMIT >> PAGE_SHIFT)) { + list_add(&page->lru, &image->unuseable_pages); + continue; + } +- addr = page_to_pfn(page) << PAGE_SHIFT; ++ addr = kexec_page_to_pfn(page) << PAGE_SHIFT; + + /* If it is the destination page we want use it */ + if (addr == destination) +@@ -757,7 +782,7 @@ static struct page *kimage_alloc_page(st + struct page *old_page; + + old_addr = *old & PAGE_MASK; +- old_page = pfn_to_page(old_addr >> PAGE_SHIFT); ++ old_page = kexec_pfn_to_page(old_addr >> PAGE_SHIFT); + copy_highpage(page, old_page); + *old = addr | (*old & ~PAGE_MASK); + +@@ -813,7 +838,7 @@ static int kimage_load_normal_segment(st + result = -ENOMEM; + goto out; + } +- result = kimage_add_page(image, page_to_pfn(page) ++ result = kimage_add_page(image, kexec_page_to_pfn(page) + << PAGE_SHIFT); + if (result < 0) + goto out; +@@ -845,6 +870,7 @@ out: + return result; + } + ++#ifndef CONFIG_XEN + static int kimage_load_crash_segment(struct kimage *image, + struct kexec_segment *segment) + { +@@ -867,7 +893,7 @@ static int kimage_load_crash_segment(str + char *ptr; + size_t uchunk, mchunk; + +- page = pfn_to_page(maddr >> PAGE_SHIFT); ++ page = kexec_pfn_to_page(maddr >> PAGE_SHIFT); + if (!page) { + result = -ENOMEM; + goto out; +@@ -916,6 +942,13 @@ static int kimage_load_segment(struct ki + + return result; + } ++#else /* CONFIG_XEN */ ++static int kimage_load_segment(struct kimage *image, ++ struct kexec_segment *segment) ++{ ++ return kimage_load_normal_segment(image, segment); ++} ++#endif + + /* + * Exec Kernel system call: for obvious reasons only root may call it. +@@ -1019,6 +1052,13 @@ SYSCALL_DEFINE4(kexec_load, unsigned lon + } + kimage_terminate(image); + } ++#ifdef CONFIG_XEN ++ if (image) { ++ result = xen_machine_kexec_load(image); ++ if (result) ++ goto out; ++ } ++#endif + /* Install the new kernel, and Uninstall the old */ + image = xchg(dest_image, image); + +--- sle11sp1-2010-03-22.orig/kernel/sysctl.c 2010-03-22 12:11:55.000000000 +0100 ++++ sle11sp1-2010-03-22/kernel/sysctl.c 2009-12-16 11:47:57.000000000 +0100 +@@ -876,7 +876,7 @@ static struct ctl_table kern_table[] = { + .proc_handler = &proc_dointvec, + }, + #endif +-#if defined(CONFIG_ACPI_SLEEP) && defined(CONFIG_X86) ++#if defined(CONFIG_ACPI_SLEEP) && defined(CONFIG_X86) && !defined(CONFIG_ACPI_PV_SLEEP) + { + .procname = "acpi_video_flags", + .data = &acpi_realmode_flags, +--- sle11sp1-2010-03-22.orig/mm/memory.c 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/mm/memory.c 2010-03-11 09:13:00.000000000 +0100 +@@ -523,6 +523,12 @@ struct page *vm_normal_page(struct vm_ar + { + unsigned long pfn = pte_pfn(pte); + ++#if defined(CONFIG_XEN) && defined(CONFIG_X86) ++ /* XEN: Covers user-space grant mappings (even of local pages). */ ++ if (unlikely(vma->vm_flags & VM_FOREIGN)) ++ return NULL; ++#endif ++ + if (HAVE_PTE_SPECIAL) { + if (likely(!pte_special(pte))) + goto check_pfn; +@@ -554,6 +560,9 @@ struct page *vm_normal_page(struct vm_ar + return NULL; + check_pfn: + if (unlikely(pfn > highest_memmap_pfn)) { ++#ifdef CONFIG_XEN ++ if (!(vma->vm_flags & VM_RESERVED)) ++#endif + print_bad_pte(vma, addr, pte, NULL); + return NULL; + } +@@ -839,8 +848,12 @@ static unsigned long zap_pte_range(struc + page->index > details->last_index)) + continue; + } +- ptent = ptep_get_and_clear_full(mm, addr, pte, +- tlb->fullmm); ++ if (unlikely(vma->vm_ops && vma->vm_ops->zap_pte)) ++ ptent = vma->vm_ops->zap_pte(vma, addr, pte, ++ tlb->fullmm); ++ else ++ ptent = ptep_get_and_clear_full(mm, addr, pte, ++ tlb->fullmm); + tlb_remove_tlb_entry(tlb, pte, addr); + if (unlikely(!page)) + continue; +@@ -1105,6 +1118,7 @@ unsigned long zap_page_range(struct vm_a + tlb_finish_mmu(tlb, address, end); + return end; + } ++EXPORT_SYMBOL(zap_page_range); + + /** + * zap_vma_ptes - remove ptes mapping the vma +@@ -1301,6 +1315,28 @@ int __get_user_pages(struct task_struct + continue; + } + ++#ifdef CONFIG_XEN ++ if (vma && (vma->vm_flags & VM_FOREIGN)) { ++ struct vm_foreign_map *foreign_map = ++ vma->vm_private_data; ++ struct page **map = foreign_map->map; ++ int offset = (start - vma->vm_start) >> PAGE_SHIFT; ++ if (map[offset] != NULL) { ++ if (pages) { ++ struct page *page = map[offset]; ++ ++ pages[i] = page; ++ get_page(page); ++ } ++ if (vmas) ++ vmas[i] = vma; ++ i++; ++ start += PAGE_SIZE; ++ len--; ++ continue; ++ } ++ } ++#endif + if (!vma || + (vma->vm_flags & (VM_IO | VM_PFNMAP)) || + !(vm_flags & vma->vm_flags)) +--- sle11sp1-2010-03-22.orig/mm/mmap.c 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/mm/mmap.c 2010-03-11 09:13:04.000000000 +0100 +@@ -1842,6 +1842,12 @@ static void unmap_region(struct mm_struc + tlb_finish_mmu(tlb, start, end); + } + ++static inline void unmap_vma(struct vm_area_struct *vma) ++{ ++ if (unlikely(vma->vm_ops && vma->vm_ops->unmap)) ++ vma->vm_ops->unmap(vma); ++} ++ + /* + * Create a list of vma's touched by the unmap, removing them from the mm's + * vma list as we go.. +@@ -1857,6 +1863,7 @@ detach_vmas_to_be_unmapped(struct mm_str + insertion_point = (prev ? &prev->vm_next : &mm->mmap); + do { + rb_erase(&vma->vm_rb, &mm->mm_rb); ++ unmap_vma(vma); + mm->map_count--; + tail_vma = vma; + vma = vma->vm_next; +@@ -2151,6 +2158,9 @@ void exit_mmap(struct mm_struct *mm) + + arch_exit_mmap(mm); + ++ for (vma = mm->mmap; vma; vma = vma->vm_next) ++ unmap_vma(vma); ++ + vma = mm->mmap; + if (!vma) /* Can happen if dup_mmap() received an OOM */ + return; +--- sle11sp1-2010-03-22.orig/mm/mprotect.c 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/mm/mprotect.c 2009-12-04 10:44:41.000000000 +0100 +@@ -91,6 +91,8 @@ static inline void change_pmd_range(stru + next = pmd_addr_end(addr, end); + if (pmd_none_or_clear_bad(pmd)) + continue; ++ if (arch_change_pte_range(mm, pmd, addr, next, newprot)) ++ continue; + change_pte_range(mm, pmd, addr, next, newprot, dirty_accountable); + } while (pmd++, addr = next, addr != end); + } +--- sle11sp1-2010-03-22.orig/mm/page_alloc.c 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/mm/page_alloc.c 2010-03-22 12:13:00.000000000 +0100 +@@ -635,6 +635,13 @@ static void __free_pages_ok(struct page + int bad = 0; + int wasMlocked = __TestClearPageMlocked(page); + ++#ifdef CONFIG_XEN ++ if (PageForeign(page)) { ++ PageForeignDestructor(page, order); ++ return; ++ } ++#endif ++ + kmemcheck_free_shadow(page, order); + + for (i = 0 ; i < (1 << order) ; ++i) +@@ -1134,6 +1141,13 @@ static void free_hot_cold_page(struct pa + int migratetype; + int wasMlocked = __TestClearPageMlocked(page); + ++#ifdef CONFIG_XEN ++ if (PageForeign(page)) { ++ PageForeignDestructor(page, 0); ++ return; ++ } ++#endif ++ + kmemcheck_free_shadow(page, 0); + + if (PageAnon(page)) +--- sle11sp1-2010-03-22.orig/net/core/dev.c 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/net/core/dev.c 2010-03-01 14:18:13.000000000 +0100 +@@ -136,6 +136,12 @@ + /* This should be increased if a protocol with a bigger head is added. */ + #define GRO_MAX_HEAD (MAX_HEADER + 128) + ++#ifdef CONFIG_XEN ++#include ++#include ++#include ++#endif ++ + /* + * The list of packet types we will receive (as opposed to discard) + * and the routines to invoke. +@@ -1809,6 +1815,43 @@ static struct netdev_queue *dev_pick_tx( + return netdev_get_tx_queue(dev, queue_index); + } + ++#ifdef CONFIG_XEN ++inline int skb_checksum_setup(struct sk_buff *skb) ++{ ++ if (skb->proto_csum_blank) { ++ if (skb->protocol != htons(ETH_P_IP)) ++ goto out; ++ skb->h.raw = (unsigned char *)skb->nh.iph + 4*skb->nh.iph->ihl; ++ if (skb->h.raw >= skb->tail) ++ goto out; ++ switch (skb->nh.iph->protocol) { ++ case IPPROTO_TCP: ++ skb->csum = offsetof(struct tcphdr, check); ++ break; ++ case IPPROTO_UDP: ++ skb->csum = offsetof(struct udphdr, check); ++ break; ++ default: ++ if (net_ratelimit()) ++ printk(KERN_ERR "Attempting to checksum a non-" ++ "TCP/UDP packet, dropping a protocol" ++ " %d packet", skb->nh.iph->protocol); ++ goto out; ++ } ++ if ((skb->h.raw + skb->csum + 2) > skb->tail) ++ goto out; ++ skb->ip_summed = CHECKSUM_HW; ++ skb->proto_csum_blank = 0; ++ } ++ return 0; ++out: ++ return -EPROTO; ++} ++#else ++inline int skb_checksum_setup(struct sk_buff *skb) { return 0; } ++#endif ++EXPORT_SYMBOL(skb_checksum_setup); ++ + static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q, + struct net_device *dev, + struct netdev_queue *txq) +@@ -1875,6 +1918,12 @@ int dev_queue_xmit(struct sk_buff *skb) + struct Qdisc *q; + int rc = -ENOMEM; + ++ /* If a checksum-deferred packet is forwarded to a device that needs a ++ * checksum, correct the pointers and force checksumming. ++ */ ++ if (skb_checksum_setup(skb)) ++ goto out_kfree_skb; ++ + /* GSO will handle the following emulations directly. */ + if (netif_needs_gso(dev, skb)) + goto gso; +@@ -2370,6 +2419,19 @@ int netif_receive_skb(struct sk_buff *sk + } + #endif + ++#ifdef CONFIG_XEN ++ switch (skb->ip_summed) { ++ case CHECKSUM_UNNECESSARY: ++ skb->proto_data_valid = 1; ++ break; ++ case CHECKSUM_HW: ++ /* XXX Implement me. */ ++ default: ++ skb->proto_data_valid = 0; ++ break; ++ } ++#endif ++ + if (skb_emergency(skb)) + goto skip_taps; + +--- sle11sp1-2010-03-22.orig/net/core/skbuff.c 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/net/core/skbuff.c 2009-12-04 10:44:41.000000000 +0100 +@@ -642,6 +642,10 @@ static struct sk_buff *__skb_clone(struc + n->hdr_len = skb->nohdr ? skb_headroom(skb) : skb->hdr_len; + n->cloned = 1; + n->nohdr = 0; ++#ifdef CONFIG_XEN ++ C(proto_data_valid); ++ C(proto_csum_blank); ++#endif + n->destructor = NULL; + C(tail); + C(end); +--- sle11sp1-2010-03-22.orig/net/ipv4/netfilter/nf_nat_proto_tcp.c 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/net/ipv4/netfilter/nf_nat_proto_tcp.c 2009-12-04 10:44:41.000000000 +0100 +@@ -75,6 +75,9 @@ tcp_manip_pkt(struct sk_buff *skb, + if (hdrsize < sizeof(*hdr)) + return true; + ++ if (skb_checksum_setup(skb)) ++ return false; ++ + inet_proto_csum_replace4(&hdr->check, skb, oldip, newip, 1); + inet_proto_csum_replace2(&hdr->check, skb, oldport, newport, 0); + return true; +--- sle11sp1-2010-03-22.orig/net/ipv4/netfilter/nf_nat_proto_udp.c 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/net/ipv4/netfilter/nf_nat_proto_udp.c 2009-12-04 10:44:41.000000000 +0100 +@@ -60,6 +60,10 @@ udp_manip_pkt(struct sk_buff *skb, + newport = tuple->dst.u.udp.port; + portptr = &hdr->dest; + } ++ ++ if (skb_checksum_setup(skb)) ++ return false; ++ + if (hdr->check || skb->ip_summed == CHECKSUM_PARTIAL) { + inet_proto_csum_replace4(&hdr->check, skb, oldip, newip, 1); + inet_proto_csum_replace2(&hdr->check, skb, *portptr, newport, +--- sle11sp1-2010-03-22.orig/net/ipv4/xfrm4_output.c 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/net/ipv4/xfrm4_output.c 2009-12-04 10:44:41.000000000 +0100 +@@ -81,7 +81,7 @@ static int xfrm4_output_finish(struct sk + #endif + + skb->protocol = htons(ETH_P_IP); +- return xfrm_output(skb); ++ return skb_checksum_setup(skb) ?: xfrm_output(skb); + } + + int xfrm4_output(struct sk_buff *skb) +--- sle11sp1-2010-03-22.orig/scripts/Makefile.build 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/scripts/Makefile.build 2009-12-04 10:44:41.000000000 +0100 +@@ -76,6 +76,21 @@ ifndef obj + $(warning kbuild: Makefile.build is included improperly) + endif + ++ifeq ($(CONFIG_XEN),y) ++Makefile.xen := $(if $(KBUILD_EXTMOD),$(KBUILD_EXTMOD),$(objtree)/scripts)/Makefile.xen ++$(Makefile.xen): $(srctree)/scripts/Makefile.xen.awk $(srctree)/scripts/Makefile.build ++ @echo ' Updating $@' ++ $(if $(shell echo a | $(AWK) '{ print gensub(/a/, "AA", "g"); }'),\ ++ ,$(error 'Your awk program does not define gensub. Use gawk or another awk with gensub')) ++ @$(AWK) -f $< $(filter-out $<,$^) >$@ ++ ++xen-src-single-used-m := $(patsubst $(srctree)/%,%,$(wildcard $(addprefix $(srctree)/,$(single-used-m:.o=-xen.c)))) ++xen-single-used-m := $(xen-src-single-used-m:-xen.c=.o) ++single-used-m := $(filter-out $(xen-single-used-m),$(single-used-m)) ++ ++-include $(Makefile.xen) ++endif ++ + # =========================================================================== + + ifneq ($(strip $(lib-y) $(lib-m) $(lib-n) $(lib-)),) +--- sle11sp1-2010-03-22.orig/scripts/Makefile.lib 2010-03-22 12:07:55.000000000 +0100 ++++ sle11sp1-2010-03-22/scripts/Makefile.lib 2009-12-04 10:44:41.000000000 +0100 +@@ -22,6 +22,12 @@ obj-m := $(filter-out $(obj-y),$(obj-m)) + + lib-y := $(filter-out $(obj-y), $(sort $(lib-y) $(lib-m))) + ++# Remove objects forcibly disabled ++ ++obj-y := $(filter-out $(disabled-obj-y),$(obj-y)) ++obj-m := $(filter-out $(disabled-obj-y),$(obj-m)) ++lib-y := $(filter-out $(disabled-obj-y),$(lib-y)) ++ + + # Handle objects in subdirs + # --------------------------------------------------------------------------- diff --git a/xen3-auto-include-xen-interface.diff b/xen3-auto-include-xen-interface.diff new file mode 100644 index 0000000..f6bea13 --- /dev/null +++ b/xen3-auto-include-xen-interface.diff @@ -0,0 +1,6149 @@ +Subject: xen3 include-xen-interface +From: http://xenbits.xensource.com/linux-2.6.18-xen.hg (tip 1011:11175e60d393) +Patch-mainline: obsolete +Acked-by: jbeulich@novell.com + +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/include/xen/interface/COPYING 2007-06-12 13:14:19.000000000 +0200 +@@ -0,0 +1,38 @@ ++XEN NOTICE ++========== ++ ++This copyright applies to all files within this subdirectory and its ++subdirectories: ++ include/public/*.h ++ include/public/hvm/*.h ++ include/public/io/*.h ++ ++The intention is that these files can be freely copied into the source ++tree of an operating system when porting that OS to run on Xen. Doing ++so does *not* cause the OS to become subject to the terms of the GPL. ++ ++All other files in the Xen source distribution are covered by version ++2 of the GNU General Public License except where explicitly stated ++otherwise within individual source files. ++ ++ -- Keir Fraser (on behalf of the Xen team) ++ ++===================================================================== ++ ++Permission is hereby granted, free of charge, to any person obtaining a copy ++of this software and associated documentation files (the "Software"), to ++deal in the Software without restriction, including without limitation the ++rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ++sell copies of the Software, and to permit persons to whom the Software is ++furnished to do so, subject to the following conditions: ++ ++The above copyright notice and this permission notice shall be included in ++all copies or substantial portions of the Software. ++ ++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ++DEALINGS IN THE SOFTWARE. +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/include/xen/interface/arch-x86/cpuid.h 2008-01-21 11:15:27.000000000 +0100 +@@ -0,0 +1,68 @@ ++/****************************************************************************** ++ * arch-x86/cpuid.h ++ * ++ * CPUID interface to Xen. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to ++ * deal in the Software without restriction, including without limitation the ++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ++ * DEALINGS IN THE SOFTWARE. ++ * ++ * Copyright (c) 2007 Citrix Systems, Inc. ++ * ++ * Authors: ++ * Keir Fraser ++ */ ++ ++#ifndef __XEN_PUBLIC_ARCH_X86_CPUID_H__ ++#define __XEN_PUBLIC_ARCH_X86_CPUID_H__ ++ ++/* Xen identification leaves start at 0x40000000. */ ++#define XEN_CPUID_FIRST_LEAF 0x40000000 ++#define XEN_CPUID_LEAF(i) (XEN_CPUID_FIRST_LEAF + (i)) ++ ++/* ++ * Leaf 1 (0x40000000) ++ * EAX: Largest Xen-information leaf. All leaves up to an including @EAX ++ * are supported by the Xen host. ++ * EBX-EDX: "XenVMMXenVMM" signature, allowing positive identification ++ * of a Xen host. ++ */ ++#define XEN_CPUID_SIGNATURE_EBX 0x566e6558 /* "XenV" */ ++#define XEN_CPUID_SIGNATURE_ECX 0x65584d4d /* "MMXe" */ ++#define XEN_CPUID_SIGNATURE_EDX 0x4d4d566e /* "nVMM" */ ++ ++/* ++ * Leaf 2 (0x40000001) ++ * EAX[31:16]: Xen major version. ++ * EAX[15: 0]: Xen minor version. ++ * EBX-EDX: Reserved (currently all zeroes). ++ */ ++ ++/* ++ * Leaf 3 (0x40000002) ++ * EAX: Number of hypercall transfer pages. This register is always guaranteed ++ * to specify one hypercall page. ++ * EBX: Base address of Xen-specific MSRs. ++ * ECX: Features 1. Unused bits are set to zero. ++ * EDX: Features 2. Unused bits are set to zero. ++ */ ++ ++/* Does the host support MMU_PT_UPDATE_PRESERVE_AD for this guest? */ ++#define _XEN_CPUID_FEAT1_MMU_PT_UPDATE_PRESERVE_AD 0 ++#define XEN_CPUID_FEAT1_MMU_PT_UPDATE_PRESERVE_AD (1u<<0) ++ ++#endif /* __XEN_PUBLIC_ARCH_X86_CPUID_H__ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/include/xen/interface/arch-x86/hvm/save.h 2010-01-04 11:56:34.000000000 +0100 +@@ -0,0 +1,439 @@ ++/* ++ * Structure definitions for HVM state that is held by Xen and must ++ * be saved along with the domain's memory and device-model state. ++ * ++ * Copyright (c) 2007 XenSource Ltd. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to ++ * deal in the Software without restriction, including without limitation the ++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ++ * DEALINGS IN THE SOFTWARE. ++ */ ++ ++#ifndef __XEN_PUBLIC_HVM_SAVE_X86_H__ ++#define __XEN_PUBLIC_HVM_SAVE_X86_H__ ++ ++/* ++ * Save/restore header: general info about the save file. ++ */ ++ ++#define HVM_FILE_MAGIC 0x54381286 ++#define HVM_FILE_VERSION 0x00000001 ++ ++struct hvm_save_header { ++ uint32_t magic; /* Must be HVM_FILE_MAGIC */ ++ uint32_t version; /* File format version */ ++ uint64_t changeset; /* Version of Xen that saved this file */ ++ uint32_t cpuid; /* CPUID[0x01][%eax] on the saving machine */ ++ uint32_t gtsc_khz; /* Guest's TSC frequency in kHz */ ++}; ++ ++DECLARE_HVM_SAVE_TYPE(HEADER, 1, struct hvm_save_header); ++ ++ ++/* ++ * Processor ++ */ ++ ++struct hvm_hw_cpu { ++ uint8_t fpu_regs[512]; ++ ++ uint64_t rax; ++ uint64_t rbx; ++ uint64_t rcx; ++ uint64_t rdx; ++ uint64_t rbp; ++ uint64_t rsi; ++ uint64_t rdi; ++ uint64_t rsp; ++ uint64_t r8; ++ uint64_t r9; ++ uint64_t r10; ++ uint64_t r11; ++ uint64_t r12; ++ uint64_t r13; ++ uint64_t r14; ++ uint64_t r15; ++ ++ uint64_t rip; ++ uint64_t rflags; ++ ++ uint64_t cr0; ++ uint64_t cr2; ++ uint64_t cr3; ++ uint64_t cr4; ++ ++ uint64_t dr0; ++ uint64_t dr1; ++ uint64_t dr2; ++ uint64_t dr3; ++ uint64_t dr6; ++ uint64_t dr7; ++ ++ uint32_t cs_sel; ++ uint32_t ds_sel; ++ uint32_t es_sel; ++ uint32_t fs_sel; ++ uint32_t gs_sel; ++ uint32_t ss_sel; ++ uint32_t tr_sel; ++ uint32_t ldtr_sel; ++ ++ uint32_t cs_limit; ++ uint32_t ds_limit; ++ uint32_t es_limit; ++ uint32_t fs_limit; ++ uint32_t gs_limit; ++ uint32_t ss_limit; ++ uint32_t tr_limit; ++ uint32_t ldtr_limit; ++ uint32_t idtr_limit; ++ uint32_t gdtr_limit; ++ ++ uint64_t cs_base; ++ uint64_t ds_base; ++ uint64_t es_base; ++ uint64_t fs_base; ++ uint64_t gs_base; ++ uint64_t ss_base; ++ uint64_t tr_base; ++ uint64_t ldtr_base; ++ uint64_t idtr_base; ++ uint64_t gdtr_base; ++ ++ uint32_t cs_arbytes; ++ uint32_t ds_arbytes; ++ uint32_t es_arbytes; ++ uint32_t fs_arbytes; ++ uint32_t gs_arbytes; ++ uint32_t ss_arbytes; ++ uint32_t tr_arbytes; ++ uint32_t ldtr_arbytes; ++ ++ uint64_t sysenter_cs; ++ uint64_t sysenter_esp; ++ uint64_t sysenter_eip; ++ ++ /* msr for em64t */ ++ uint64_t shadow_gs; ++ ++ /* msr content saved/restored. */ ++ uint64_t msr_flags; ++ uint64_t msr_lstar; ++ uint64_t msr_star; ++ uint64_t msr_cstar; ++ uint64_t msr_syscall_mask; ++ uint64_t msr_efer; ++ uint64_t msr_tsc_aux; ++ ++ /* guest's idea of what rdtsc() would return */ ++ uint64_t tsc; ++ ++ /* pending event, if any */ ++ union { ++ uint32_t pending_event; ++ struct { ++ uint8_t pending_vector:8; ++ uint8_t pending_type:3; ++ uint8_t pending_error_valid:1; ++ uint32_t pending_reserved:19; ++ uint8_t pending_valid:1; ++ }; ++ }; ++ /* error code for pending event */ ++ uint32_t error_code; ++}; ++ ++DECLARE_HVM_SAVE_TYPE(CPU, 2, struct hvm_hw_cpu); ++ ++ ++/* ++ * PIC ++ */ ++ ++struct hvm_hw_vpic { ++ /* IR line bitmasks. */ ++ uint8_t irr; ++ uint8_t imr; ++ uint8_t isr; ++ ++ /* Line IRx maps to IRQ irq_base+x */ ++ uint8_t irq_base; ++ ++ /* ++ * Where are we in ICW2-4 initialisation (0 means no init in progress)? ++ * Bits 0-1 (=x): Next write at A=1 sets ICW(x+1). ++ * Bit 2: ICW1.IC4 (1 == ICW4 included in init sequence) ++ * Bit 3: ICW1.SNGL (0 == ICW3 included in init sequence) ++ */ ++ uint8_t init_state:4; ++ ++ /* IR line with highest priority. */ ++ uint8_t priority_add:4; ++ ++ /* Reads from A=0 obtain ISR or IRR? */ ++ uint8_t readsel_isr:1; ++ ++ /* Reads perform a polling read? */ ++ uint8_t poll:1; ++ ++ /* Automatically clear IRQs from the ISR during INTA? */ ++ uint8_t auto_eoi:1; ++ ++ /* Automatically rotate IRQ priorities during AEOI? */ ++ uint8_t rotate_on_auto_eoi:1; ++ ++ /* Exclude slave inputs when considering in-service IRQs? */ ++ uint8_t special_fully_nested_mode:1; ++ ++ /* Special mask mode excludes masked IRs from AEOI and priority checks. */ ++ uint8_t special_mask_mode:1; ++ ++ /* Is this a master PIC or slave PIC? (NB. This is not programmable.) */ ++ uint8_t is_master:1; ++ ++ /* Edge/trigger selection. */ ++ uint8_t elcr; ++ ++ /* Virtual INT output. */ ++ uint8_t int_output; ++}; ++ ++DECLARE_HVM_SAVE_TYPE(PIC, 3, struct hvm_hw_vpic); ++ ++ ++/* ++ * IO-APIC ++ */ ++ ++#ifdef __ia64__ ++#define VIOAPIC_IS_IOSAPIC 1 ++#define VIOAPIC_NUM_PINS 24 ++#else ++#define VIOAPIC_NUM_PINS 48 /* 16 ISA IRQs, 32 non-legacy PCI IRQS. */ ++#endif ++ ++struct hvm_hw_vioapic { ++ uint64_t base_address; ++ uint32_t ioregsel; ++ uint32_t id; ++ union vioapic_redir_entry ++ { ++ uint64_t bits; ++ struct { ++ uint8_t vector; ++ uint8_t delivery_mode:3; ++ uint8_t dest_mode:1; ++ uint8_t delivery_status:1; ++ uint8_t polarity:1; ++ uint8_t remote_irr:1; ++ uint8_t trig_mode:1; ++ uint8_t mask:1; ++ uint8_t reserve:7; ++#if !VIOAPIC_IS_IOSAPIC ++ uint8_t reserved[4]; ++ uint8_t dest_id; ++#else ++ uint8_t reserved[3]; ++ uint16_t dest_id; ++#endif ++ } fields; ++ } redirtbl[VIOAPIC_NUM_PINS]; ++}; ++ ++DECLARE_HVM_SAVE_TYPE(IOAPIC, 4, struct hvm_hw_vioapic); ++ ++ ++/* ++ * LAPIC ++ */ ++ ++struct hvm_hw_lapic { ++ uint64_t apic_base_msr; ++ uint32_t disabled; /* VLAPIC_xx_DISABLED */ ++ uint32_t timer_divisor; ++}; ++ ++DECLARE_HVM_SAVE_TYPE(LAPIC, 5, struct hvm_hw_lapic); ++ ++struct hvm_hw_lapic_regs { ++ uint8_t data[1024]; ++}; ++ ++DECLARE_HVM_SAVE_TYPE(LAPIC_REGS, 6, struct hvm_hw_lapic_regs); ++ ++ ++/* ++ * IRQs ++ */ ++ ++struct hvm_hw_pci_irqs { ++ /* ++ * Virtual interrupt wires for a single PCI bus. ++ * Indexed by: device*4 + INTx#. ++ */ ++ union { ++ unsigned long i[16 / sizeof (unsigned long)]; /* DECLARE_BITMAP(i, 32*4); */ ++ uint64_t pad[2]; ++ }; ++}; ++ ++DECLARE_HVM_SAVE_TYPE(PCI_IRQ, 7, struct hvm_hw_pci_irqs); ++ ++struct hvm_hw_isa_irqs { ++ /* ++ * Virtual interrupt wires for ISA devices. ++ * Indexed by ISA IRQ (assumes no ISA-device IRQ sharing). ++ */ ++ union { ++ unsigned long i[1]; /* DECLARE_BITMAP(i, 16); */ ++ uint64_t pad[1]; ++ }; ++}; ++ ++DECLARE_HVM_SAVE_TYPE(ISA_IRQ, 8, struct hvm_hw_isa_irqs); ++ ++struct hvm_hw_pci_link { ++ /* ++ * PCI-ISA interrupt router. ++ * Each PCI is 'wire-ORed' into one of four links using ++ * the traditional 'barber's pole' mapping ((device + INTx#) & 3). ++ * The router provides a programmable mapping from each link to a GSI. ++ */ ++ uint8_t route[4]; ++ uint8_t pad0[4]; ++}; ++ ++DECLARE_HVM_SAVE_TYPE(PCI_LINK, 9, struct hvm_hw_pci_link); ++ ++/* ++ * PIT ++ */ ++ ++struct hvm_hw_pit { ++ struct hvm_hw_pit_channel { ++ uint32_t count; /* can be 65536 */ ++ uint16_t latched_count; ++ uint8_t count_latched; ++ uint8_t status_latched; ++ uint8_t status; ++ uint8_t read_state; ++ uint8_t write_state; ++ uint8_t write_latch; ++ uint8_t rw_mode; ++ uint8_t mode; ++ uint8_t bcd; /* not supported */ ++ uint8_t gate; /* timer start */ ++ } channels[3]; /* 3 x 16 bytes */ ++ uint32_t speaker_data_on; ++ uint32_t pad0; ++}; ++ ++DECLARE_HVM_SAVE_TYPE(PIT, 10, struct hvm_hw_pit); ++ ++ ++/* ++ * RTC ++ */ ++ ++#define RTC_CMOS_SIZE 14 ++struct hvm_hw_rtc { ++ /* CMOS bytes */ ++ uint8_t cmos_data[RTC_CMOS_SIZE]; ++ /* Index register for 2-part operations */ ++ uint8_t cmos_index; ++ uint8_t pad0; ++}; ++ ++DECLARE_HVM_SAVE_TYPE(RTC, 11, struct hvm_hw_rtc); ++ ++ ++/* ++ * HPET ++ */ ++ ++#define HPET_TIMER_NUM 3 /* 3 timers supported now */ ++struct hvm_hw_hpet { ++ /* Memory-mapped, software visible registers */ ++ uint64_t capability; /* capabilities */ ++ uint64_t res0; /* reserved */ ++ uint64_t config; /* configuration */ ++ uint64_t res1; /* reserved */ ++ uint64_t isr; /* interrupt status reg */ ++ uint64_t res2[25]; /* reserved */ ++ uint64_t mc64; /* main counter */ ++ uint64_t res3; /* reserved */ ++ struct { /* timers */ ++ uint64_t config; /* configuration/cap */ ++ uint64_t cmp; /* comparator */ ++ uint64_t fsb; /* FSB route, not supported now */ ++ uint64_t res4; /* reserved */ ++ } timers[HPET_TIMER_NUM]; ++ uint64_t res5[4*(24-HPET_TIMER_NUM)]; /* reserved, up to 0x3ff */ ++ ++ /* Hidden register state */ ++ uint64_t period[HPET_TIMER_NUM]; /* Last value written to comparator */ ++}; ++ ++DECLARE_HVM_SAVE_TYPE(HPET, 12, struct hvm_hw_hpet); ++ ++ ++/* ++ * PM timer ++ */ ++ ++struct hvm_hw_pmtimer { ++ uint32_t tmr_val; /* PM_TMR_BLK.TMR_VAL: 32bit free-running counter */ ++ uint16_t pm1a_sts; /* PM1a_EVT_BLK.PM1a_STS: status register */ ++ uint16_t pm1a_en; /* PM1a_EVT_BLK.PM1a_EN: enable register */ ++}; ++ ++DECLARE_HVM_SAVE_TYPE(PMTIMER, 13, struct hvm_hw_pmtimer); ++ ++/* ++ * MTRR MSRs ++ */ ++ ++struct hvm_hw_mtrr { ++#define MTRR_VCNT 8 ++#define NUM_FIXED_MSR 11 ++ uint64_t msr_pat_cr; ++ /* mtrr physbase & physmask msr pair*/ ++ uint64_t msr_mtrr_var[MTRR_VCNT*2]; ++ uint64_t msr_mtrr_fixed[NUM_FIXED_MSR]; ++ uint64_t msr_mtrr_cap; ++ uint64_t msr_mtrr_def_type; ++}; ++ ++DECLARE_HVM_SAVE_TYPE(MTRR, 14, struct hvm_hw_mtrr); ++ ++/* ++ * Viridian hypervisor context. ++ */ ++ ++struct hvm_viridian_context { ++ uint64_t hypercall_gpa; ++ uint64_t guest_os_id; ++}; ++ ++DECLARE_HVM_SAVE_TYPE(VIRIDIAN, 15, struct hvm_viridian_context); ++ ++/* ++ * Largest type-code in use ++ */ ++#define HVM_SAVE_CODE_MAX 15 ++ ++#endif /* __XEN_PUBLIC_HVM_SAVE_X86_H__ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/include/xen/interface/arch-x86/xen-mca.h 2009-05-19 09:16:41.000000000 +0200 +@@ -0,0 +1,422 @@ ++/****************************************************************************** ++ * arch-x86/mca.h ++ * ++ * Contributed by Advanced Micro Devices, Inc. ++ * Author: Christoph Egger ++ * ++ * Guest OS machine check interface to x86 Xen. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to ++ * deal in the Software without restriction, including without limitation the ++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ++ * DEALINGS IN THE SOFTWARE. ++ */ ++ ++/* Full MCA functionality has the following Usecases from the guest side: ++ * ++ * Must have's: ++ * 1. Dom0 and DomU register machine check trap callback handlers ++ * (already done via "set_trap_table" hypercall) ++ * 2. Dom0 registers machine check event callback handler ++ * (doable via EVTCHNOP_bind_virq) ++ * 3. Dom0 and DomU fetches machine check data ++ * 4. Dom0 wants Xen to notify a DomU ++ * 5. Dom0 gets DomU ID from physical address ++ * 6. Dom0 wants Xen to kill DomU (already done for "xm destroy") ++ * ++ * Nice to have's: ++ * 7. Dom0 wants Xen to deactivate a physical CPU ++ * This is better done as separate task, physical CPU hotplugging, ++ * and hypercall(s) should be sysctl's ++ * 8. Page migration proposed from Xen NUMA work, where Dom0 can tell Xen to ++ * move a DomU (or Dom0 itself) away from a malicious page ++ * producing correctable errors. ++ * 9. offlining physical page: ++ * Xen free's and never re-uses a certain physical page. ++ * 10. Testfacility: Allow Dom0 to write values into machine check MSR's ++ * and tell Xen to trigger a machine check ++ */ ++ ++#ifndef __XEN_PUBLIC_ARCH_X86_MCA_H__ ++#define __XEN_PUBLIC_ARCH_X86_MCA_H__ ++ ++/* Hypercall */ ++#define __HYPERVISOR_mca __HYPERVISOR_arch_0 ++ ++/* ++ * The xen-unstable repo has interface version 0x03000001; out interface ++ * is incompatible with that and any future minor revisions, so we ++ * choose a different version number range that is numerically less ++ * than that used in xen-unstable. ++ */ ++#define XEN_MCA_INTERFACE_VERSION 0x01ecc003 ++ ++/* IN: Dom0 calls hypercall to retrieve nonurgent telemetry */ ++#define XEN_MC_NONURGENT 0x0001 ++/* IN: Dom0/DomU calls hypercall to retrieve urgent telemetry */ ++#define XEN_MC_URGENT 0x0002 ++/* IN: Dom0 acknowledges previosly-fetched telemetry */ ++#define XEN_MC_ACK 0x0004 ++ ++/* OUT: All is ok */ ++#define XEN_MC_OK 0x0 ++/* OUT: Domain could not fetch data. */ ++#define XEN_MC_FETCHFAILED 0x1 ++/* OUT: There was no machine check data to fetch. */ ++#define XEN_MC_NODATA 0x2 ++/* OUT: Between notification time and this hypercall an other ++ * (most likely) correctable error happened. The fetched data, ++ * does not match the original machine check data. */ ++#define XEN_MC_NOMATCH 0x4 ++ ++/* OUT: DomU did not register MC NMI handler. Try something else. */ ++#define XEN_MC_CANNOTHANDLE 0x8 ++/* OUT: Notifying DomU failed. Retry later or try something else. */ ++#define XEN_MC_NOTDELIVERED 0x10 ++/* Note, XEN_MC_CANNOTHANDLE and XEN_MC_NOTDELIVERED are mutually exclusive. */ ++ ++ ++#ifndef __ASSEMBLY__ ++ ++#define VIRQ_MCA VIRQ_ARCH_0 /* G. (DOM0) Machine Check Architecture */ ++ ++/* ++ * Machine Check Architecure: ++ * structs are read-only and used to report all kinds of ++ * correctable and uncorrectable errors detected by the HW. ++ * Dom0 and DomU: register a handler to get notified. ++ * Dom0 only: Correctable errors are reported via VIRQ_MCA ++ * Dom0 and DomU: Uncorrectable errors are reported via nmi handlers ++ */ ++#define MC_TYPE_GLOBAL 0 ++#define MC_TYPE_BANK 1 ++#define MC_TYPE_EXTENDED 2 ++#define MC_TYPE_RECOVERY 3 ++ ++struct mcinfo_common { ++ uint16_t type; /* structure type */ ++ uint16_t size; /* size of this struct in bytes */ ++}; ++ ++ ++#define MC_FLAG_CORRECTABLE (1 << 0) ++#define MC_FLAG_UNCORRECTABLE (1 << 1) ++#define MC_FLAG_RECOVERABLE (1 << 2) ++#define MC_FLAG_POLLED (1 << 3) ++#define MC_FLAG_RESET (1 << 4) ++#define MC_FLAG_CMCI (1 << 5) ++#define MC_FLAG_MCE (1 << 6) ++/* contains global x86 mc information */ ++struct mcinfo_global { ++ struct mcinfo_common common; ++ ++ /* running domain at the time in error (most likely the impacted one) */ ++ uint16_t mc_domid; ++ uint16_t mc_vcpuid; /* virtual cpu scheduled for mc_domid */ ++ uint32_t mc_socketid; /* physical socket of the physical core */ ++ uint16_t mc_coreid; /* physical impacted core */ ++ uint16_t mc_core_threadid; /* core thread of physical core */ ++ uint32_t mc_apicid; ++ uint32_t mc_flags; ++ uint64_t mc_gstatus; /* global status */ ++}; ++ ++/* contains bank local x86 mc information */ ++struct mcinfo_bank { ++ struct mcinfo_common common; ++ ++ uint16_t mc_bank; /* bank nr */ ++ uint16_t mc_domid; /* Usecase 5: domain referenced by mc_addr on dom0 ++ * and if mc_addr is valid. Never valid on DomU. */ ++ uint64_t mc_status; /* bank status */ ++ uint64_t mc_addr; /* bank address, only valid ++ * if addr bit is set in mc_status */ ++ uint64_t mc_misc; ++ uint64_t mc_ctrl2; ++ uint64_t mc_tsc; ++}; ++ ++ ++struct mcinfo_msr { ++ uint64_t reg; /* MSR */ ++ uint64_t value; /* MSR value */ ++}; ++ ++/* contains mc information from other ++ * or additional mc MSRs */ ++struct mcinfo_extended { ++ struct mcinfo_common common; ++ ++ /* You can fill up to five registers. ++ * If you need more, then use this structure ++ * multiple times. */ ++ ++ uint32_t mc_msrs; /* Number of msr with valid values. */ ++ /* ++ * Currently Intel extended MSR (32/64) include all gp registers ++ * and E(R)FLAGS, E(R)IP, E(R)MISC, up to 11/19 of them might be ++ * useful at present. So expand this array to 16/32 to leave room. ++ */ ++ struct mcinfo_msr mc_msr[sizeof(void *) * 4]; ++}; ++ ++/* Recovery Action flags. Giving recovery result information to DOM0 */ ++ ++/* Xen takes successful recovery action, the error is recovered */ ++#define REC_ACTION_RECOVERED (0x1 << 0) ++/* No action is performed by XEN */ ++#define REC_ACTION_NONE (0x1 << 1) ++/* It's possible DOM0 might take action ownership in some case */ ++#define REC_ACTION_NEED_RESET (0x1 << 2) ++ ++/* Different Recovery Action types, if the action is performed successfully, ++ * REC_ACTION_RECOVERED flag will be returned. ++ */ ++ ++/* Page Offline Action */ ++#define MC_ACTION_PAGE_OFFLINE (0x1 << 0) ++/* CPU offline Action */ ++#define MC_ACTION_CPU_OFFLINE (0x1 << 1) ++/* L3 cache disable Action */ ++#define MC_ACTION_CACHE_SHRINK (0x1 << 2) ++ ++/* Below interface used between XEN/DOM0 for passing XEN's recovery action ++ * information to DOM0. ++ * usage Senario: After offlining broken page, XEN might pass its page offline ++ * recovery action result to DOM0. DOM0 will save the information in ++ * non-volatile memory for further proactive actions, such as offlining the ++ * easy broken page earlier when doing next reboot. ++*/ ++struct page_offline_action ++{ ++ /* Params for passing the offlined page number to DOM0 */ ++ uint64_t mfn; ++ uint64_t status; ++}; ++ ++struct cpu_offline_action ++{ ++ /* Params for passing the identity of the offlined CPU to DOM0 */ ++ uint32_t mc_socketid; ++ uint16_t mc_coreid; ++ uint16_t mc_core_threadid; ++}; ++ ++#define MAX_UNION_SIZE 16 ++struct mcinfo_recovery ++{ ++ struct mcinfo_common common; ++ uint16_t mc_bank; /* bank nr */ ++ uint8_t action_flags; ++ uint8_t action_types; ++ union { ++ struct page_offline_action page_retire; ++ struct cpu_offline_action cpu_offline; ++ uint8_t pad[MAX_UNION_SIZE]; ++ } action_info; ++}; ++ ++ ++#define MCINFO_HYPERCALLSIZE 1024 ++#define MCINFO_MAXSIZE 768 ++ ++struct mc_info { ++ /* Number of mcinfo_* entries in mi_data */ ++ uint32_t mi_nentries; ++ uint32_t _pad0; ++ uint64_t mi_data[(MCINFO_MAXSIZE - 1) / 8]; ++}; ++typedef struct mc_info mc_info_t; ++DEFINE_XEN_GUEST_HANDLE(mc_info_t); ++ ++#define __MC_MSR_ARRAYSIZE 8 ++#define __MC_NMSRS 1 ++#define MC_NCAPS 7 /* 7 CPU feature flag words */ ++#define MC_CAPS_STD_EDX 0 /* cpuid level 0x00000001 (%edx) */ ++#define MC_CAPS_AMD_EDX 1 /* cpuid level 0x80000001 (%edx) */ ++#define MC_CAPS_TM 2 /* cpuid level 0x80860001 (TransMeta) */ ++#define MC_CAPS_LINUX 3 /* Linux-defined */ ++#define MC_CAPS_STD_ECX 4 /* cpuid level 0x00000001 (%ecx) */ ++#define MC_CAPS_VIA 5 /* cpuid level 0xc0000001 */ ++#define MC_CAPS_AMD_ECX 6 /* cpuid level 0x80000001 (%ecx) */ ++ ++struct mcinfo_logical_cpu { ++ uint32_t mc_cpunr; ++ uint32_t mc_chipid; ++ uint16_t mc_coreid; ++ uint16_t mc_threadid; ++ uint32_t mc_apicid; ++ uint32_t mc_clusterid; ++ uint32_t mc_ncores; ++ uint32_t mc_ncores_active; ++ uint32_t mc_nthreads; ++ int32_t mc_cpuid_level; ++ uint32_t mc_family; ++ uint32_t mc_vendor; ++ uint32_t mc_model; ++ uint32_t mc_step; ++ char mc_vendorid[16]; ++ char mc_brandid[64]; ++ uint32_t mc_cpu_caps[MC_NCAPS]; ++ uint32_t mc_cache_size; ++ uint32_t mc_cache_alignment; ++ int32_t mc_nmsrvals; ++ struct mcinfo_msr mc_msrvalues[__MC_MSR_ARRAYSIZE]; ++}; ++typedef struct mcinfo_logical_cpu xen_mc_logical_cpu_t; ++DEFINE_XEN_GUEST_HANDLE(xen_mc_logical_cpu_t); ++ ++ ++/* ++ * OS's should use these instead of writing their own lookup function ++ * each with its own bugs and drawbacks. ++ * We use macros instead of static inline functions to allow guests ++ * to include this header in assembly files (*.S). ++ */ ++/* Prototype: ++ * uint32_t x86_mcinfo_nentries(struct mc_info *mi); ++ */ ++#define x86_mcinfo_nentries(_mi) \ ++ (_mi)->mi_nentries ++/* Prototype: ++ * struct mcinfo_common *x86_mcinfo_first(struct mc_info *mi); ++ */ ++#define x86_mcinfo_first(_mi) \ ++ ((struct mcinfo_common *)(_mi)->mi_data) ++/* Prototype: ++ * struct mcinfo_common *x86_mcinfo_next(struct mcinfo_common *mic); ++ */ ++#define x86_mcinfo_next(_mic) \ ++ ((struct mcinfo_common *)((uint8_t *)(_mic) + (_mic)->size)) ++ ++/* Prototype: ++ * void x86_mcinfo_lookup(void *ret, struct mc_info *mi, uint16_t type); ++ */ ++#define x86_mcinfo_lookup(_ret, _mi, _type) \ ++ do { \ ++ uint32_t found, i; \ ++ struct mcinfo_common *_mic; \ ++ \ ++ found = 0; \ ++ (_ret) = NULL; \ ++ if (_mi == NULL) break; \ ++ _mic = x86_mcinfo_first(_mi); \ ++ for (i = 0; i < x86_mcinfo_nentries(_mi); i++) { \ ++ if (_mic->type == (_type)) { \ ++ found = 1; \ ++ break; \ ++ } \ ++ _mic = x86_mcinfo_next(_mic); \ ++ } \ ++ (_ret) = found ? _mic : NULL; \ ++ } while (0) ++ ++ ++/* Usecase 1 ++ * Register machine check trap callback handler ++ * (already done via "set_trap_table" hypercall) ++ */ ++ ++/* Usecase 2 ++ * Dom0 registers machine check event callback handler ++ * done by EVTCHNOP_bind_virq ++ */ ++ ++/* Usecase 3 ++ * Fetch machine check data from hypervisor. ++ * Note, this hypercall is special, because both Dom0 and DomU must use this. ++ */ ++#define XEN_MC_fetch 1 ++struct xen_mc_fetch { ++ /* IN/OUT variables. */ ++ uint32_t flags; /* IN: XEN_MC_NONURGENT, XEN_MC_URGENT, ++ XEN_MC_ACK if ack'ing an earlier fetch */ ++ /* OUT: XEN_MC_OK, XEN_MC_FETCHFAILED, ++ XEN_MC_NODATA, XEN_MC_NOMATCH */ ++ uint32_t _pad0; ++ uint64_t fetch_id; /* OUT: id for ack, IN: id we are ack'ing */ ++ ++ /* OUT variables. */ ++ XEN_GUEST_HANDLE(mc_info_t) data; ++}; ++typedef struct xen_mc_fetch xen_mc_fetch_t; ++DEFINE_XEN_GUEST_HANDLE(xen_mc_fetch_t); ++ ++ ++/* Usecase 4 ++ * This tells the hypervisor to notify a DomU about the machine check error ++ */ ++#define XEN_MC_notifydomain 2 ++struct xen_mc_notifydomain { ++ /* IN variables. */ ++ uint16_t mc_domid; /* The unprivileged domain to notify. */ ++ uint16_t mc_vcpuid; /* The vcpu in mc_domid to notify. ++ * Usually echo'd value from the fetch hypercall. */ ++ ++ /* IN/OUT variables. */ ++ uint32_t flags; ++ ++/* IN: XEN_MC_CORRECTABLE, XEN_MC_TRAP */ ++/* OUT: XEN_MC_OK, XEN_MC_CANNOTHANDLE, XEN_MC_NOTDELIVERED, XEN_MC_NOMATCH */ ++}; ++typedef struct xen_mc_notifydomain xen_mc_notifydomain_t; ++DEFINE_XEN_GUEST_HANDLE(xen_mc_notifydomain_t); ++ ++#define XEN_MC_physcpuinfo 3 ++struct xen_mc_physcpuinfo { ++ /* IN/OUT */ ++ uint32_t ncpus; ++ uint32_t _pad0; ++ /* OUT */ ++ XEN_GUEST_HANDLE(xen_mc_logical_cpu_t) info; ++}; ++ ++#define XEN_MC_msrinject 4 ++#define MC_MSRINJ_MAXMSRS 8 ++struct xen_mc_msrinject { ++ /* IN */ ++ uint32_t mcinj_cpunr; /* target processor id */ ++ uint32_t mcinj_flags; /* see MC_MSRINJ_F_* below */ ++ uint32_t mcinj_count; /* 0 .. count-1 in array are valid */ ++ uint32_t _pad0; ++ struct mcinfo_msr mcinj_msr[MC_MSRINJ_MAXMSRS]; ++}; ++ ++/* Flags for mcinj_flags above; bits 16-31 are reserved */ ++#define MC_MSRINJ_F_INTERPOSE 0x1 ++ ++#define XEN_MC_mceinject 5 ++struct xen_mc_mceinject { ++ unsigned int mceinj_cpunr; /* target processor id */ ++}; ++ ++struct xen_mc { ++ uint32_t cmd; ++ uint32_t interface_version; /* XEN_MCA_INTERFACE_VERSION */ ++ union { ++ struct xen_mc_fetch mc_fetch; ++ struct xen_mc_notifydomain mc_notifydomain; ++ struct xen_mc_physcpuinfo mc_physcpuinfo; ++ struct xen_mc_msrinject mc_msrinject; ++ struct xen_mc_mceinject mc_mceinject; ++ } u; ++}; ++typedef struct xen_mc xen_mc_t; ++DEFINE_XEN_GUEST_HANDLE(xen_mc_t); ++ ++#endif /* __ASSEMBLY__ */ ++ ++#endif /* __XEN_PUBLIC_ARCH_X86_MCA_H__ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/include/xen/interface/arch-x86/xen-x86_32.h 2008-07-21 11:00:33.000000000 +0200 +@@ -0,0 +1,180 @@ ++/****************************************************************************** ++ * xen-x86_32.h ++ * ++ * Guest OS interface to x86 32-bit Xen. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to ++ * deal in the Software without restriction, including without limitation the ++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ++ * DEALINGS IN THE SOFTWARE. ++ * ++ * Copyright (c) 2004-2007, K A Fraser ++ */ ++ ++#ifndef __XEN_PUBLIC_ARCH_X86_XEN_X86_32_H__ ++#define __XEN_PUBLIC_ARCH_X86_XEN_X86_32_H__ ++ ++/* ++ * Hypercall interface: ++ * Input: %ebx, %ecx, %edx, %esi, %edi (arguments 1-5) ++ * Output: %eax ++ * Access is via hypercall page (set up by guest loader or via a Xen MSR): ++ * call hypercall_page + hypercall-number * 32 ++ * Clobbered: Argument registers (e.g., 2-arg hypercall clobbers %ebx,%ecx) ++ */ ++ ++#if __XEN_INTERFACE_VERSION__ < 0x00030203 ++/* ++ * Legacy hypercall interface: ++ * As above, except the entry sequence to the hypervisor is: ++ * mov $hypercall-number*32,%eax ; int $0x82 ++ */ ++#define TRAP_INSTR "int $0x82" ++#endif ++ ++/* ++ * These flat segments are in the Xen-private section of every GDT. Since these ++ * are also present in the initial GDT, many OSes will be able to avoid ++ * installing their own GDT. ++ */ ++#define FLAT_RING1_CS 0xe019 /* GDT index 259 */ ++#define FLAT_RING1_DS 0xe021 /* GDT index 260 */ ++#define FLAT_RING1_SS 0xe021 /* GDT index 260 */ ++#define FLAT_RING3_CS 0xe02b /* GDT index 261 */ ++#define FLAT_RING3_DS 0xe033 /* GDT index 262 */ ++#define FLAT_RING3_SS 0xe033 /* GDT index 262 */ ++ ++#define FLAT_KERNEL_CS FLAT_RING1_CS ++#define FLAT_KERNEL_DS FLAT_RING1_DS ++#define FLAT_KERNEL_SS FLAT_RING1_SS ++#define FLAT_USER_CS FLAT_RING3_CS ++#define FLAT_USER_DS FLAT_RING3_DS ++#define FLAT_USER_SS FLAT_RING3_SS ++ ++#define __HYPERVISOR_VIRT_START_PAE 0xF5800000 ++#define __MACH2PHYS_VIRT_START_PAE 0xF5800000 ++#define __MACH2PHYS_VIRT_END_PAE 0xF6800000 ++#define HYPERVISOR_VIRT_START_PAE \ ++ mk_unsigned_long(__HYPERVISOR_VIRT_START_PAE) ++#define MACH2PHYS_VIRT_START_PAE \ ++ mk_unsigned_long(__MACH2PHYS_VIRT_START_PAE) ++#define MACH2PHYS_VIRT_END_PAE \ ++ mk_unsigned_long(__MACH2PHYS_VIRT_END_PAE) ++ ++/* Non-PAE bounds are obsolete. */ ++#define __HYPERVISOR_VIRT_START_NONPAE 0xFC000000 ++#define __MACH2PHYS_VIRT_START_NONPAE 0xFC000000 ++#define __MACH2PHYS_VIRT_END_NONPAE 0xFC400000 ++#define HYPERVISOR_VIRT_START_NONPAE \ ++ mk_unsigned_long(__HYPERVISOR_VIRT_START_NONPAE) ++#define MACH2PHYS_VIRT_START_NONPAE \ ++ mk_unsigned_long(__MACH2PHYS_VIRT_START_NONPAE) ++#define MACH2PHYS_VIRT_END_NONPAE \ ++ mk_unsigned_long(__MACH2PHYS_VIRT_END_NONPAE) ++ ++#define __HYPERVISOR_VIRT_START __HYPERVISOR_VIRT_START_PAE ++#define __MACH2PHYS_VIRT_START __MACH2PHYS_VIRT_START_PAE ++#define __MACH2PHYS_VIRT_END __MACH2PHYS_VIRT_END_PAE ++ ++#ifndef HYPERVISOR_VIRT_START ++#define HYPERVISOR_VIRT_START mk_unsigned_long(__HYPERVISOR_VIRT_START) ++#endif ++ ++#define MACH2PHYS_VIRT_START mk_unsigned_long(__MACH2PHYS_VIRT_START) ++#define MACH2PHYS_VIRT_END mk_unsigned_long(__MACH2PHYS_VIRT_END) ++#define MACH2PHYS_NR_ENTRIES ((MACH2PHYS_VIRT_END-MACH2PHYS_VIRT_START)>>2) ++#ifndef machine_to_phys_mapping ++#define machine_to_phys_mapping ((unsigned long *)MACH2PHYS_VIRT_START) ++#endif ++ ++/* 32-/64-bit invariability for control interfaces (domctl/sysctl). */ ++#if defined(__XEN__) || defined(__XEN_TOOLS__) ++#undef ___DEFINE_XEN_GUEST_HANDLE ++#define ___DEFINE_XEN_GUEST_HANDLE(name, type) \ ++ typedef struct { type *p; } \ ++ __guest_handle_ ## name; \ ++ typedef struct { union { type *p; uint64_aligned_t q; }; } \ ++ __guest_handle_64_ ## name ++#undef set_xen_guest_handle ++#define set_xen_guest_handle(hnd, val) \ ++ do { if ( sizeof(hnd) == 8 ) *(uint64_t *)&(hnd) = 0; \ ++ (hnd).p = val; \ ++ } while ( 0 ) ++#define uint64_aligned_t uint64_t __attribute__((aligned(8))) ++#define __XEN_GUEST_HANDLE_64(name) __guest_handle_64_ ## name ++#define XEN_GUEST_HANDLE_64(name) __XEN_GUEST_HANDLE_64(name) ++#endif ++ ++#ifndef __ASSEMBLY__ ++ ++struct cpu_user_regs { ++ uint32_t ebx; ++ uint32_t ecx; ++ uint32_t edx; ++ uint32_t esi; ++ uint32_t edi; ++ uint32_t ebp; ++ uint32_t eax; ++ uint16_t error_code; /* private */ ++ uint16_t entry_vector; /* private */ ++ uint32_t eip; ++ uint16_t cs; ++ uint8_t saved_upcall_mask; ++ uint8_t _pad0; ++ uint32_t eflags; /* eflags.IF == !saved_upcall_mask */ ++ uint32_t esp; ++ uint16_t ss, _pad1; ++ uint16_t es, _pad2; ++ uint16_t ds, _pad3; ++ uint16_t fs, _pad4; ++ uint16_t gs, _pad5; ++}; ++typedef struct cpu_user_regs cpu_user_regs_t; ++DEFINE_XEN_GUEST_HANDLE(cpu_user_regs_t); ++ ++/* ++ * Page-directory addresses above 4GB do not fit into architectural %cr3. ++ * When accessing %cr3, or equivalent field in vcpu_guest_context, guests ++ * must use the following accessor macros to pack/unpack valid MFNs. ++ */ ++#define xen_pfn_to_cr3(pfn) (((unsigned)(pfn) << 12) | ((unsigned)(pfn) >> 20)) ++#define xen_cr3_to_pfn(cr3) (((unsigned)(cr3) >> 12) | ((unsigned)(cr3) << 20)) ++ ++struct arch_vcpu_info { ++ unsigned long cr2; ++ unsigned long pad[5]; /* sizeof(vcpu_info_t) == 64 */ ++}; ++typedef struct arch_vcpu_info arch_vcpu_info_t; ++ ++struct xen_callback { ++ unsigned long cs; ++ unsigned long eip; ++}; ++typedef struct xen_callback xen_callback_t; ++ ++#endif /* !__ASSEMBLY__ */ ++ ++#endif /* __XEN_PUBLIC_ARCH_X86_XEN_X86_32_H__ */ ++ ++/* ++ * Local variables: ++ * mode: C ++ * c-set-style: "BSD" ++ * c-basic-offset: 4 ++ * tab-width: 4 ++ * indent-tabs-mode: nil ++ * End: ++ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/include/xen/interface/arch-x86/xen-x86_64.h 2008-04-02 12:34:02.000000000 +0200 +@@ -0,0 +1,212 @@ ++/****************************************************************************** ++ * xen-x86_64.h ++ * ++ * Guest OS interface to x86 64-bit Xen. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to ++ * deal in the Software without restriction, including without limitation the ++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ++ * DEALINGS IN THE SOFTWARE. ++ * ++ * Copyright (c) 2004-2006, K A Fraser ++ */ ++ ++#ifndef __XEN_PUBLIC_ARCH_X86_XEN_X86_64_H__ ++#define __XEN_PUBLIC_ARCH_X86_XEN_X86_64_H__ ++ ++/* ++ * Hypercall interface: ++ * Input: %rdi, %rsi, %rdx, %r10, %r8 (arguments 1-5) ++ * Output: %rax ++ * Access is via hypercall page (set up by guest loader or via a Xen MSR): ++ * call hypercall_page + hypercall-number * 32 ++ * Clobbered: argument registers (e.g., 2-arg hypercall clobbers %rdi,%rsi) ++ */ ++ ++#if __XEN_INTERFACE_VERSION__ < 0x00030203 ++/* ++ * Legacy hypercall interface: ++ * As above, except the entry sequence to the hypervisor is: ++ * mov $hypercall-number*32,%eax ; syscall ++ * Clobbered: %rcx, %r11, argument registers (as above) ++ */ ++#define TRAP_INSTR "syscall" ++#endif ++ ++/* ++ * 64-bit segment selectors ++ * These flat segments are in the Xen-private section of every GDT. Since these ++ * are also present in the initial GDT, many OSes will be able to avoid ++ * installing their own GDT. ++ */ ++ ++#define FLAT_RING3_CS32 0xe023 /* GDT index 260 */ ++#define FLAT_RING3_CS64 0xe033 /* GDT index 261 */ ++#define FLAT_RING3_DS32 0xe02b /* GDT index 262 */ ++#define FLAT_RING3_DS64 0x0000 /* NULL selector */ ++#define FLAT_RING3_SS32 0xe02b /* GDT index 262 */ ++#define FLAT_RING3_SS64 0xe02b /* GDT index 262 */ ++ ++#define FLAT_KERNEL_DS64 FLAT_RING3_DS64 ++#define FLAT_KERNEL_DS32 FLAT_RING3_DS32 ++#define FLAT_KERNEL_DS FLAT_KERNEL_DS64 ++#define FLAT_KERNEL_CS64 FLAT_RING3_CS64 ++#define FLAT_KERNEL_CS32 FLAT_RING3_CS32 ++#define FLAT_KERNEL_CS FLAT_KERNEL_CS64 ++#define FLAT_KERNEL_SS64 FLAT_RING3_SS64 ++#define FLAT_KERNEL_SS32 FLAT_RING3_SS32 ++#define FLAT_KERNEL_SS FLAT_KERNEL_SS64 ++ ++#define FLAT_USER_DS64 FLAT_RING3_DS64 ++#define FLAT_USER_DS32 FLAT_RING3_DS32 ++#define FLAT_USER_DS FLAT_USER_DS64 ++#define FLAT_USER_CS64 FLAT_RING3_CS64 ++#define FLAT_USER_CS32 FLAT_RING3_CS32 ++#define FLAT_USER_CS FLAT_USER_CS64 ++#define FLAT_USER_SS64 FLAT_RING3_SS64 ++#define FLAT_USER_SS32 FLAT_RING3_SS32 ++#define FLAT_USER_SS FLAT_USER_SS64 ++ ++#define __HYPERVISOR_VIRT_START 0xFFFF800000000000 ++#define __HYPERVISOR_VIRT_END 0xFFFF880000000000 ++#define __MACH2PHYS_VIRT_START 0xFFFF800000000000 ++#define __MACH2PHYS_VIRT_END 0xFFFF804000000000 ++ ++#ifndef HYPERVISOR_VIRT_START ++#define HYPERVISOR_VIRT_START mk_unsigned_long(__HYPERVISOR_VIRT_START) ++#define HYPERVISOR_VIRT_END mk_unsigned_long(__HYPERVISOR_VIRT_END) ++#endif ++ ++#define MACH2PHYS_VIRT_START mk_unsigned_long(__MACH2PHYS_VIRT_START) ++#define MACH2PHYS_VIRT_END mk_unsigned_long(__MACH2PHYS_VIRT_END) ++#define MACH2PHYS_NR_ENTRIES ((MACH2PHYS_VIRT_END-MACH2PHYS_VIRT_START)>>3) ++#ifndef machine_to_phys_mapping ++#define machine_to_phys_mapping ((unsigned long *)HYPERVISOR_VIRT_START) ++#endif ++ ++/* ++ * int HYPERVISOR_set_segment_base(unsigned int which, unsigned long base) ++ * @which == SEGBASE_* ; @base == 64-bit base address ++ * Returns 0 on success. ++ */ ++#define SEGBASE_FS 0 ++#define SEGBASE_GS_USER 1 ++#define SEGBASE_GS_KERNEL 2 ++#define SEGBASE_GS_USER_SEL 3 /* Set user %gs specified in base[15:0] */ ++ ++/* ++ * int HYPERVISOR_iret(void) ++ * All arguments are on the kernel stack, in the following format. ++ * Never returns if successful. Current kernel context is lost. ++ * The saved CS is mapped as follows: ++ * RING0 -> RING3 kernel mode. ++ * RING1 -> RING3 kernel mode. ++ * RING2 -> RING3 kernel mode. ++ * RING3 -> RING3 user mode. ++ * However RING0 indicates that the guest kernel should return to iteself ++ * directly with ++ * orb $3,1*8(%rsp) ++ * iretq ++ * If flags contains VGCF_in_syscall: ++ * Restore RAX, RIP, RFLAGS, RSP. ++ * Discard R11, RCX, CS, SS. ++ * Otherwise: ++ * Restore RAX, R11, RCX, CS:RIP, RFLAGS, SS:RSP. ++ * All other registers are saved on hypercall entry and restored to user. ++ */ ++/* Guest exited in SYSCALL context? Return to guest with SYSRET? */ ++#define _VGCF_in_syscall 8 ++#define VGCF_in_syscall (1<<_VGCF_in_syscall) ++#define VGCF_IN_SYSCALL VGCF_in_syscall ++ ++#ifndef __ASSEMBLY__ ++ ++struct iret_context { ++ /* Top of stack (%rsp at point of hypercall). */ ++ uint64_t rax, r11, rcx, flags, rip, cs, rflags, rsp, ss; ++ /* Bottom of iret stack frame. */ ++}; ++ ++#if defined(__GNUC__) && !defined(__STRICT_ANSI__) ++/* Anonymous union includes both 32- and 64-bit names (e.g., eax/rax). */ ++#define __DECL_REG(name) union { \ ++ uint64_t r ## name, e ## name; \ ++ uint32_t _e ## name; \ ++} ++#else ++/* Non-gcc sources must always use the proper 64-bit name (e.g., rax). */ ++#define __DECL_REG(name) uint64_t r ## name ++#endif ++ ++struct cpu_user_regs { ++ uint64_t r15; ++ uint64_t r14; ++ uint64_t r13; ++ uint64_t r12; ++ __DECL_REG(bp); ++ __DECL_REG(bx); ++ uint64_t r11; ++ uint64_t r10; ++ uint64_t r9; ++ uint64_t r8; ++ __DECL_REG(ax); ++ __DECL_REG(cx); ++ __DECL_REG(dx); ++ __DECL_REG(si); ++ __DECL_REG(di); ++ uint32_t error_code; /* private */ ++ uint32_t entry_vector; /* private */ ++ __DECL_REG(ip); ++ uint16_t cs, _pad0[1]; ++ uint8_t saved_upcall_mask; ++ uint8_t _pad1[3]; ++ __DECL_REG(flags); /* rflags.IF == !saved_upcall_mask */ ++ __DECL_REG(sp); ++ uint16_t ss, _pad2[3]; ++ uint16_t es, _pad3[3]; ++ uint16_t ds, _pad4[3]; ++ uint16_t fs, _pad5[3]; /* Non-zero => takes precedence over fs_base. */ ++ uint16_t gs, _pad6[3]; /* Non-zero => takes precedence over gs_base_usr. */ ++}; ++typedef struct cpu_user_regs cpu_user_regs_t; ++DEFINE_XEN_GUEST_HANDLE(cpu_user_regs_t); ++ ++#undef __DECL_REG ++ ++#define xen_pfn_to_cr3(pfn) ((unsigned long)(pfn) << 12) ++#define xen_cr3_to_pfn(cr3) ((unsigned long)(cr3) >> 12) ++ ++struct arch_vcpu_info { ++ unsigned long cr2; ++ unsigned long pad; /* sizeof(vcpu_info_t) == 64 */ ++}; ++typedef struct arch_vcpu_info arch_vcpu_info_t; ++ ++typedef unsigned long xen_callback_t; ++ ++#endif /* !__ASSEMBLY__ */ ++ ++#endif /* __XEN_PUBLIC_ARCH_X86_XEN_X86_64_H__ */ ++ ++/* ++ * Local variables: ++ * mode: C ++ * c-set-style: "BSD" ++ * c-basic-offset: 4 ++ * tab-width: 4 ++ * indent-tabs-mode: nil ++ * End: ++ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/include/xen/interface/arch-x86/xen.h 2010-01-04 11:56:34.000000000 +0100 +@@ -0,0 +1,200 @@ ++/****************************************************************************** ++ * arch-x86/xen.h ++ * ++ * Guest OS interface to x86 Xen. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to ++ * deal in the Software without restriction, including without limitation the ++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ++ * DEALINGS IN THE SOFTWARE. ++ * ++ * Copyright (c) 2004-2006, K A Fraser ++ */ ++ ++#include "../xen.h" ++ ++#ifndef __XEN_PUBLIC_ARCH_X86_XEN_H__ ++#define __XEN_PUBLIC_ARCH_X86_XEN_H__ ++ ++/* Structural guest handles introduced in 0x00030201. */ ++#if __XEN_INTERFACE_VERSION__ >= 0x00030201 ++#define ___DEFINE_XEN_GUEST_HANDLE(name, type) \ ++ typedef struct { type *p; } __guest_handle_ ## name ++#else ++#define ___DEFINE_XEN_GUEST_HANDLE(name, type) \ ++ typedef type * __guest_handle_ ## name ++#endif ++ ++#define __DEFINE_XEN_GUEST_HANDLE(name, type) \ ++ ___DEFINE_XEN_GUEST_HANDLE(name, type); \ ++ ___DEFINE_XEN_GUEST_HANDLE(const_##name, const type) ++#define DEFINE_XEN_GUEST_HANDLE(name) __DEFINE_XEN_GUEST_HANDLE(name, name) ++#define __XEN_GUEST_HANDLE(name) __guest_handle_ ## name ++#define XEN_GUEST_HANDLE(name) __XEN_GUEST_HANDLE(name) ++#define set_xen_guest_handle(hnd, val) do { (hnd).p = val; } while (0) ++#ifdef __XEN_TOOLS__ ++#define get_xen_guest_handle(val, hnd) do { val = (hnd).p; } while (0) ++#endif ++ ++#if defined(__i386__) ++#include "xen-x86_32.h" ++#elif defined(__x86_64__) ++#include "xen-x86_64.h" ++#endif ++ ++#ifndef __ASSEMBLY__ ++typedef unsigned long xen_pfn_t; ++#define PRI_xen_pfn "lx" ++#endif ++ ++/* ++ * SEGMENT DESCRIPTOR TABLES ++ */ ++/* ++ * A number of GDT entries are reserved by Xen. These are not situated at the ++ * start of the GDT because some stupid OSes export hard-coded selector values ++ * in their ABI. These hard-coded values are always near the start of the GDT, ++ * so Xen places itself out of the way, at the far end of the GDT. ++ */ ++#define FIRST_RESERVED_GDT_PAGE 14 ++#define FIRST_RESERVED_GDT_BYTE (FIRST_RESERVED_GDT_PAGE * 4096) ++#define FIRST_RESERVED_GDT_ENTRY (FIRST_RESERVED_GDT_BYTE / 8) ++ ++/* Maximum number of virtual CPUs in legacy multi-processor guests. */ ++#define XEN_LEGACY_MAX_VCPUS 32 ++ ++#ifndef __ASSEMBLY__ ++ ++typedef unsigned long xen_ulong_t; ++ ++/* ++ * Send an array of these to HYPERVISOR_set_trap_table(). ++ * The privilege level specifies which modes may enter a trap via a software ++ * interrupt. On x86/64, since rings 1 and 2 are unavailable, we allocate ++ * privilege levels as follows: ++ * Level == 0: Noone may enter ++ * Level == 1: Kernel may enter ++ * Level == 2: Kernel may enter ++ * Level == 3: Everyone may enter ++ */ ++#define TI_GET_DPL(_ti) ((_ti)->flags & 3) ++#define TI_GET_IF(_ti) ((_ti)->flags & 4) ++#define TI_SET_DPL(_ti,_dpl) ((_ti)->flags |= (_dpl)) ++#define TI_SET_IF(_ti,_if) ((_ti)->flags |= ((!!(_if))<<2)) ++struct trap_info { ++ uint8_t vector; /* exception vector */ ++ uint8_t flags; /* 0-3: privilege level; 4: clear event enable? */ ++ uint16_t cs; /* code selector */ ++ unsigned long address; /* code offset */ ++}; ++typedef struct trap_info trap_info_t; ++DEFINE_XEN_GUEST_HANDLE(trap_info_t); ++ ++typedef uint64_t tsc_timestamp_t; /* RDTSC timestamp */ ++ ++/* ++ * The following is all CPU context. Note that the fpu_ctxt block is filled ++ * in by FXSAVE if the CPU has feature FXSR; otherwise FSAVE is used. ++ */ ++struct vcpu_guest_context { ++ /* FPU registers come first so they can be aligned for FXSAVE/FXRSTOR. */ ++ struct { char x[512]; } fpu_ctxt; /* User-level FPU registers */ ++#define VGCF_I387_VALID (1<<0) ++#define VGCF_IN_KERNEL (1<<2) ++#define _VGCF_i387_valid 0 ++#define VGCF_i387_valid (1<<_VGCF_i387_valid) ++#define _VGCF_in_kernel 2 ++#define VGCF_in_kernel (1<<_VGCF_in_kernel) ++#define _VGCF_failsafe_disables_events 3 ++#define VGCF_failsafe_disables_events (1<<_VGCF_failsafe_disables_events) ++#define _VGCF_syscall_disables_events 4 ++#define VGCF_syscall_disables_events (1<<_VGCF_syscall_disables_events) ++#define _VGCF_online 5 ++#define VGCF_online (1<<_VGCF_online) ++ unsigned long flags; /* VGCF_* flags */ ++ struct cpu_user_regs user_regs; /* User-level CPU registers */ ++ struct trap_info trap_ctxt[256]; /* Virtual IDT */ ++ unsigned long ldt_base, ldt_ents; /* LDT (linear address, # ents) */ ++ unsigned long gdt_frames[16], gdt_ents; /* GDT (machine frames, # ents) */ ++ unsigned long kernel_ss, kernel_sp; /* Virtual TSS (only SS1/SP1) */ ++ /* NB. User pagetable on x86/64 is placed in ctrlreg[1]. */ ++ unsigned long ctrlreg[8]; /* CR0-CR7 (control registers) */ ++ unsigned long debugreg[8]; /* DB0-DB7 (debug registers) */ ++#ifdef __i386__ ++ unsigned long event_callback_cs; /* CS:EIP of event callback */ ++ unsigned long event_callback_eip; ++ unsigned long failsafe_callback_cs; /* CS:EIP of failsafe callback */ ++ unsigned long failsafe_callback_eip; ++#else ++ unsigned long event_callback_eip; ++ unsigned long failsafe_callback_eip; ++#ifdef __XEN__ ++ union { ++ unsigned long syscall_callback_eip; ++ struct { ++ unsigned int event_callback_cs; /* compat CS of event cb */ ++ unsigned int failsafe_callback_cs; /* compat CS of failsafe cb */ ++ }; ++ }; ++#else ++ unsigned long syscall_callback_eip; ++#endif ++#endif ++ unsigned long vm_assist; /* VMASST_TYPE_* bitmap */ ++#ifdef __x86_64__ ++ /* Segment base addresses. */ ++ uint64_t fs_base; ++ uint64_t gs_base_kernel; ++ uint64_t gs_base_user; ++#endif ++}; ++typedef struct vcpu_guest_context vcpu_guest_context_t; ++DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t); ++ ++struct arch_shared_info { ++ unsigned long max_pfn; /* max pfn that appears in table */ ++ /* Frame containing list of mfns containing list of mfns containing p2m. */ ++ xen_pfn_t pfn_to_mfn_frame_list_list; ++ unsigned long nmi_reason; ++ uint64_t pad[32]; ++}; ++typedef struct arch_shared_info arch_shared_info_t; ++ ++#endif /* !__ASSEMBLY__ */ ++ ++/* ++ * Prefix forces emulation of some non-trapping instructions. ++ * Currently only CPUID. ++ */ ++#ifdef __ASSEMBLY__ ++#define XEN_EMULATE_PREFIX .byte 0x0f,0x0b,0x78,0x65,0x6e ; ++#define XEN_CPUID XEN_EMULATE_PREFIX cpuid ++#else ++#define XEN_EMULATE_PREFIX ".byte 0x0f,0x0b,0x78,0x65,0x6e ; " ++#define XEN_CPUID XEN_EMULATE_PREFIX "cpuid" ++#endif ++ ++#endif /* __XEN_PUBLIC_ARCH_X86_XEN_H__ */ ++ ++/* ++ * Local variables: ++ * mode: C ++ * c-set-style: "BSD" ++ * c-basic-offset: 4 ++ * tab-width: 4 ++ * indent-tabs-mode: nil ++ * End: ++ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/include/xen/interface/arch-x86_32.h 2007-06-12 13:14:19.000000000 +0200 +@@ -0,0 +1,27 @@ ++/****************************************************************************** ++ * arch-x86_32.h ++ * ++ * Guest OS interface to x86 32-bit Xen. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to ++ * deal in the Software without restriction, including without limitation the ++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ++ * DEALINGS IN THE SOFTWARE. ++ * ++ * Copyright (c) 2004-2006, K A Fraser ++ */ ++ ++#include "arch-x86/xen.h" +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/include/xen/interface/arch-x86_64.h 2007-06-12 13:14:19.000000000 +0200 +@@ -0,0 +1,27 @@ ++/****************************************************************************** ++ * arch-x86_64.h ++ * ++ * Guest OS interface to x86 64-bit Xen. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to ++ * deal in the Software without restriction, including without limitation the ++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ++ * DEALINGS IN THE SOFTWARE. ++ * ++ * Copyright (c) 2004-2006, K A Fraser ++ */ ++ ++#include "arch-x86/xen.h" +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/include/xen/interface/dom0_ops.h 2007-06-12 13:14:19.000000000 +0200 +@@ -0,0 +1,120 @@ ++/****************************************************************************** ++ * dom0_ops.h ++ * ++ * Process command requests from domain-0 guest OS. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to ++ * deal in the Software without restriction, including without limitation the ++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ++ * DEALINGS IN THE SOFTWARE. ++ * ++ * Copyright (c) 2002-2003, B Dragovic ++ * Copyright (c) 2002-2006, K Fraser ++ */ ++ ++#ifndef __XEN_PUBLIC_DOM0_OPS_H__ ++#define __XEN_PUBLIC_DOM0_OPS_H__ ++ ++#include "xen.h" ++#include "platform.h" ++ ++#if __XEN_INTERFACE_VERSION__ >= 0x00030204 ++#error "dom0_ops.h is a compatibility interface only" ++#endif ++ ++#define DOM0_INTERFACE_VERSION XENPF_INTERFACE_VERSION ++ ++#define DOM0_SETTIME XENPF_settime ++#define dom0_settime xenpf_settime ++#define dom0_settime_t xenpf_settime_t ++ ++#define DOM0_ADD_MEMTYPE XENPF_add_memtype ++#define dom0_add_memtype xenpf_add_memtype ++#define dom0_add_memtype_t xenpf_add_memtype_t ++ ++#define DOM0_DEL_MEMTYPE XENPF_del_memtype ++#define dom0_del_memtype xenpf_del_memtype ++#define dom0_del_memtype_t xenpf_del_memtype_t ++ ++#define DOM0_READ_MEMTYPE XENPF_read_memtype ++#define dom0_read_memtype xenpf_read_memtype ++#define dom0_read_memtype_t xenpf_read_memtype_t ++ ++#define DOM0_MICROCODE XENPF_microcode_update ++#define dom0_microcode xenpf_microcode_update ++#define dom0_microcode_t xenpf_microcode_update_t ++ ++#define DOM0_PLATFORM_QUIRK XENPF_platform_quirk ++#define dom0_platform_quirk xenpf_platform_quirk ++#define dom0_platform_quirk_t xenpf_platform_quirk_t ++ ++typedef uint64_t cpumap_t; ++ ++/* Unsupported legacy operation -- defined for API compatibility. */ ++#define DOM0_MSR 15 ++struct dom0_msr { ++ /* IN variables. */ ++ uint32_t write; ++ cpumap_t cpu_mask; ++ uint32_t msr; ++ uint32_t in1; ++ uint32_t in2; ++ /* OUT variables. */ ++ uint32_t out1; ++ uint32_t out2; ++}; ++typedef struct dom0_msr dom0_msr_t; ++DEFINE_XEN_GUEST_HANDLE(dom0_msr_t); ++ ++/* Unsupported legacy operation -- defined for API compatibility. */ ++#define DOM0_PHYSICAL_MEMORY_MAP 40 ++struct dom0_memory_map_entry { ++ uint64_t start, end; ++ uint32_t flags; /* reserved */ ++ uint8_t is_ram; ++}; ++typedef struct dom0_memory_map_entry dom0_memory_map_entry_t; ++DEFINE_XEN_GUEST_HANDLE(dom0_memory_map_entry_t); ++ ++struct dom0_op { ++ uint32_t cmd; ++ uint32_t interface_version; /* DOM0_INTERFACE_VERSION */ ++ union { ++ struct dom0_msr msr; ++ struct dom0_settime settime; ++ struct dom0_add_memtype add_memtype; ++ struct dom0_del_memtype del_memtype; ++ struct dom0_read_memtype read_memtype; ++ struct dom0_microcode microcode; ++ struct dom0_platform_quirk platform_quirk; ++ struct dom0_memory_map_entry physical_memory_map; ++ uint8_t pad[128]; ++ } u; ++}; ++typedef struct dom0_op dom0_op_t; ++DEFINE_XEN_GUEST_HANDLE(dom0_op_t); ++ ++#endif /* __XEN_PUBLIC_DOM0_OPS_H__ */ ++ ++/* ++ * Local variables: ++ * mode: C ++ * c-set-style: "BSD" ++ * c-basic-offset: 4 ++ * tab-width: 4 ++ * indent-tabs-mode: nil ++ * End: ++ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/include/xen/interface/domctl.h 2010-01-07 09:38:29.000000000 +0100 +@@ -0,0 +1,904 @@ ++/****************************************************************************** ++ * domctl.h ++ * ++ * Domain management operations. For use by node control stack. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to ++ * deal in the Software without restriction, including without limitation the ++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ++ * DEALINGS IN THE SOFTWARE. ++ * ++ * Copyright (c) 2002-2003, B Dragovic ++ * Copyright (c) 2002-2006, K Fraser ++ */ ++ ++#ifndef __XEN_PUBLIC_DOMCTL_H__ ++#define __XEN_PUBLIC_DOMCTL_H__ ++ ++#if !defined(__XEN__) && !defined(__XEN_TOOLS__) ++#error "domctl operations are intended for use by node control tools only" ++#endif ++ ++#include "xen.h" ++#include "grant_table.h" ++ ++#define XEN_DOMCTL_INTERFACE_VERSION 0x00000006 ++ ++struct xenctl_cpumap { ++ XEN_GUEST_HANDLE_64(uint8) bitmap; ++ uint32_t nr_cpus; ++}; ++ ++/* ++ * NB. xen_domctl.domain is an IN/OUT parameter for this operation. ++ * If it is specified as zero, an id is auto-allocated and returned. ++ */ ++/* XEN_DOMCTL_createdomain */ ++struct xen_domctl_createdomain { ++ /* IN parameters */ ++ uint32_t ssidref; ++ xen_domain_handle_t handle; ++ /* Is this an HVM guest (as opposed to a PV guest)? */ ++#define _XEN_DOMCTL_CDF_hvm_guest 0 ++#define XEN_DOMCTL_CDF_hvm_guest (1U<<_XEN_DOMCTL_CDF_hvm_guest) ++ /* Use hardware-assisted paging if available? */ ++#define _XEN_DOMCTL_CDF_hap 1 ++#define XEN_DOMCTL_CDF_hap (1U<<_XEN_DOMCTL_CDF_hap) ++ /* Should domain memory integrity be verifed by tboot during Sx? */ ++#define _XEN_DOMCTL_CDF_s3_integrity 2 ++#define XEN_DOMCTL_CDF_s3_integrity (1U<<_XEN_DOMCTL_CDF_s3_integrity) ++ uint32_t flags; ++ /* Disable out-of-sync shadow page tables? */ ++#define _XEN_DOMCTL_CDF_oos_off 3 ++#define XEN_DOMCTL_CDF_oos_off (1U<<_XEN_DOMCTL_CDF_oos_off) ++}; ++typedef struct xen_domctl_createdomain xen_domctl_createdomain_t; ++DEFINE_XEN_GUEST_HANDLE(xen_domctl_createdomain_t); ++ ++/* XEN_DOMCTL_getdomaininfo */ ++struct xen_domctl_getdomaininfo { ++ /* OUT variables. */ ++ domid_t domain; /* Also echoed in domctl.domain */ ++ /* Domain is scheduled to die. */ ++#define _XEN_DOMINF_dying 0 ++#define XEN_DOMINF_dying (1U<<_XEN_DOMINF_dying) ++ /* Domain is an HVM guest (as opposed to a PV guest). */ ++#define _XEN_DOMINF_hvm_guest 1 ++#define XEN_DOMINF_hvm_guest (1U<<_XEN_DOMINF_hvm_guest) ++ /* The guest OS has shut down. */ ++#define _XEN_DOMINF_shutdown 2 ++#define XEN_DOMINF_shutdown (1U<<_XEN_DOMINF_shutdown) ++ /* Currently paused by control software. */ ++#define _XEN_DOMINF_paused 3 ++#define XEN_DOMINF_paused (1U<<_XEN_DOMINF_paused) ++ /* Currently blocked pending an event. */ ++#define _XEN_DOMINF_blocked 4 ++#define XEN_DOMINF_blocked (1U<<_XEN_DOMINF_blocked) ++ /* Domain is currently running. */ ++#define _XEN_DOMINF_running 5 ++#define XEN_DOMINF_running (1U<<_XEN_DOMINF_running) ++ /* Being debugged. */ ++#define _XEN_DOMINF_debugged 6 ++#define XEN_DOMINF_debugged (1U<<_XEN_DOMINF_debugged) ++ /* XEN_DOMINF_shutdown guest-supplied code. */ ++#define XEN_DOMINF_shutdownmask 255 ++#define XEN_DOMINF_shutdownshift 16 ++ uint32_t flags; /* XEN_DOMINF_* */ ++ uint64_aligned_t tot_pages; ++ uint64_aligned_t max_pages; ++ uint64_aligned_t shr_pages; ++ uint64_aligned_t shared_info_frame; /* GMFN of shared_info struct */ ++ uint64_aligned_t cpu_time; ++ uint32_t nr_online_vcpus; /* Number of VCPUs currently online. */ ++ uint32_t max_vcpu_id; /* Maximum VCPUID in use by this domain. */ ++ uint32_t ssidref; ++ xen_domain_handle_t handle; ++}; ++typedef struct xen_domctl_getdomaininfo xen_domctl_getdomaininfo_t; ++DEFINE_XEN_GUEST_HANDLE(xen_domctl_getdomaininfo_t); ++ ++ ++/* XEN_DOMCTL_getmemlist */ ++struct xen_domctl_getmemlist { ++ /* IN variables. */ ++ /* Max entries to write to output buffer. */ ++ uint64_aligned_t max_pfns; ++ /* Start index in guest's page list. */ ++ uint64_aligned_t start_pfn; ++ XEN_GUEST_HANDLE_64(uint64) buffer; ++ /* OUT variables. */ ++ uint64_aligned_t num_pfns; ++}; ++typedef struct xen_domctl_getmemlist xen_domctl_getmemlist_t; ++DEFINE_XEN_GUEST_HANDLE(xen_domctl_getmemlist_t); ++ ++ ++/* XEN_DOMCTL_getpageframeinfo */ ++ ++#define XEN_DOMCTL_PFINFO_LTAB_SHIFT 28 ++#define XEN_DOMCTL_PFINFO_NOTAB (0x0U<<28) ++#define XEN_DOMCTL_PFINFO_L1TAB (0x1U<<28) ++#define XEN_DOMCTL_PFINFO_L2TAB (0x2U<<28) ++#define XEN_DOMCTL_PFINFO_L3TAB (0x3U<<28) ++#define XEN_DOMCTL_PFINFO_L4TAB (0x4U<<28) ++#define XEN_DOMCTL_PFINFO_LTABTYPE_MASK (0x7U<<28) ++#define XEN_DOMCTL_PFINFO_LPINTAB (0x1U<<31) ++#define XEN_DOMCTL_PFINFO_XTAB (0xfU<<28) /* invalid page */ ++#define XEN_DOMCTL_PFINFO_PAGEDTAB (0x8U<<28) ++#define XEN_DOMCTL_PFINFO_LTAB_MASK (0xfU<<28) ++ ++struct xen_domctl_getpageframeinfo { ++ /* IN variables. */ ++ uint64_aligned_t gmfn; /* GMFN to query */ ++ /* OUT variables. */ ++ /* Is the page PINNED to a type? */ ++ uint32_t type; /* see above type defs */ ++}; ++typedef struct xen_domctl_getpageframeinfo xen_domctl_getpageframeinfo_t; ++DEFINE_XEN_GUEST_HANDLE(xen_domctl_getpageframeinfo_t); ++ ++ ++/* XEN_DOMCTL_getpageframeinfo2 */ ++struct xen_domctl_getpageframeinfo2 { ++ /* IN variables. */ ++ uint64_aligned_t num; ++ /* IN/OUT variables. */ ++ XEN_GUEST_HANDLE_64(uint32) array; ++}; ++typedef struct xen_domctl_getpageframeinfo2 xen_domctl_getpageframeinfo2_t; ++DEFINE_XEN_GUEST_HANDLE(xen_domctl_getpageframeinfo2_t); ++ ++ ++/* ++ * Control shadow pagetables operation ++ */ ++/* XEN_DOMCTL_shadow_op */ ++ ++/* Disable shadow mode. */ ++#define XEN_DOMCTL_SHADOW_OP_OFF 0 ++ ++/* Enable shadow mode (mode contains ORed XEN_DOMCTL_SHADOW_ENABLE_* flags). */ ++#define XEN_DOMCTL_SHADOW_OP_ENABLE 32 ++ ++/* Log-dirty bitmap operations. */ ++ /* Return the bitmap and clean internal copy for next round. */ ++#define XEN_DOMCTL_SHADOW_OP_CLEAN 11 ++ /* Return the bitmap but do not modify internal copy. */ ++#define XEN_DOMCTL_SHADOW_OP_PEEK 12 ++ ++/* Memory allocation accessors. */ ++#define XEN_DOMCTL_SHADOW_OP_GET_ALLOCATION 30 ++#define XEN_DOMCTL_SHADOW_OP_SET_ALLOCATION 31 ++ ++/* Legacy enable operations. */ ++ /* Equiv. to ENABLE with no mode flags. */ ++#define XEN_DOMCTL_SHADOW_OP_ENABLE_TEST 1 ++ /* Equiv. to ENABLE with mode flag ENABLE_LOG_DIRTY. */ ++#define XEN_DOMCTL_SHADOW_OP_ENABLE_LOGDIRTY 2 ++ /* Equiv. to ENABLE with mode flags ENABLE_REFCOUNT and ENABLE_TRANSLATE. */ ++#define XEN_DOMCTL_SHADOW_OP_ENABLE_TRANSLATE 3 ++ ++/* Mode flags for XEN_DOMCTL_SHADOW_OP_ENABLE. */ ++ /* ++ * Shadow pagetables are refcounted: guest does not use explicit mmu ++ * operations nor write-protect its pagetables. ++ */ ++#define XEN_DOMCTL_SHADOW_ENABLE_REFCOUNT (1 << 1) ++ /* ++ * Log pages in a bitmap as they are dirtied. ++ * Used for live relocation to determine which pages must be re-sent. ++ */ ++#define XEN_DOMCTL_SHADOW_ENABLE_LOG_DIRTY (1 << 2) ++ /* ++ * Automatically translate GPFNs into MFNs. ++ */ ++#define XEN_DOMCTL_SHADOW_ENABLE_TRANSLATE (1 << 3) ++ /* ++ * Xen does not steal virtual address space from the guest. ++ * Requires HVM support. ++ */ ++#define XEN_DOMCTL_SHADOW_ENABLE_EXTERNAL (1 << 4) ++ ++struct xen_domctl_shadow_op_stats { ++ uint32_t fault_count; ++ uint32_t dirty_count; ++}; ++typedef struct xen_domctl_shadow_op_stats xen_domctl_shadow_op_stats_t; ++DEFINE_XEN_GUEST_HANDLE(xen_domctl_shadow_op_stats_t); ++ ++struct xen_domctl_shadow_op { ++ /* IN variables. */ ++ uint32_t op; /* XEN_DOMCTL_SHADOW_OP_* */ ++ ++ /* OP_ENABLE */ ++ uint32_t mode; /* XEN_DOMCTL_SHADOW_ENABLE_* */ ++ ++ /* OP_GET_ALLOCATION / OP_SET_ALLOCATION */ ++ uint32_t mb; /* Shadow memory allocation in MB */ ++ ++ /* OP_PEEK / OP_CLEAN */ ++ XEN_GUEST_HANDLE_64(uint8) dirty_bitmap; ++ uint64_aligned_t pages; /* Size of buffer. Updated with actual size. */ ++ struct xen_domctl_shadow_op_stats stats; ++}; ++typedef struct xen_domctl_shadow_op xen_domctl_shadow_op_t; ++DEFINE_XEN_GUEST_HANDLE(xen_domctl_shadow_op_t); ++ ++ ++/* XEN_DOMCTL_max_mem */ ++struct xen_domctl_max_mem { ++ /* IN variables. */ ++ uint64_aligned_t max_memkb; ++}; ++typedef struct xen_domctl_max_mem xen_domctl_max_mem_t; ++DEFINE_XEN_GUEST_HANDLE(xen_domctl_max_mem_t); ++ ++ ++/* XEN_DOMCTL_setvcpucontext */ ++/* XEN_DOMCTL_getvcpucontext */ ++struct xen_domctl_vcpucontext { ++ uint32_t vcpu; /* IN */ ++ XEN_GUEST_HANDLE_64(vcpu_guest_context_t) ctxt; /* IN/OUT */ ++}; ++typedef struct xen_domctl_vcpucontext xen_domctl_vcpucontext_t; ++DEFINE_XEN_GUEST_HANDLE(xen_domctl_vcpucontext_t); ++ ++ ++/* XEN_DOMCTL_getvcpuinfo */ ++struct xen_domctl_getvcpuinfo { ++ /* IN variables. */ ++ uint32_t vcpu; ++ /* OUT variables. */ ++ uint8_t online; /* currently online (not hotplugged)? */ ++ uint8_t blocked; /* blocked waiting for an event? */ ++ uint8_t running; /* currently scheduled on its CPU? */ ++ uint64_aligned_t cpu_time; /* total cpu time consumed (ns) */ ++ uint32_t cpu; /* current mapping */ ++}; ++typedef struct xen_domctl_getvcpuinfo xen_domctl_getvcpuinfo_t; ++DEFINE_XEN_GUEST_HANDLE(xen_domctl_getvcpuinfo_t); ++ ++ ++/* Get/set which physical cpus a vcpu can execute on. */ ++/* XEN_DOMCTL_setvcpuaffinity */ ++/* XEN_DOMCTL_getvcpuaffinity */ ++struct xen_domctl_vcpuaffinity { ++ uint32_t vcpu; /* IN */ ++ struct xenctl_cpumap cpumap; /* IN/OUT */ ++}; ++typedef struct xen_domctl_vcpuaffinity xen_domctl_vcpuaffinity_t; ++DEFINE_XEN_GUEST_HANDLE(xen_domctl_vcpuaffinity_t); ++ ++ ++/* XEN_DOMCTL_max_vcpus */ ++struct xen_domctl_max_vcpus { ++ uint32_t max; /* maximum number of vcpus */ ++}; ++typedef struct xen_domctl_max_vcpus xen_domctl_max_vcpus_t; ++DEFINE_XEN_GUEST_HANDLE(xen_domctl_max_vcpus_t); ++ ++ ++/* XEN_DOMCTL_scheduler_op */ ++/* Scheduler types. */ ++#define XEN_SCHEDULER_SEDF 4 ++#define XEN_SCHEDULER_CREDIT 5 ++/* Set or get info? */ ++#define XEN_DOMCTL_SCHEDOP_putinfo 0 ++#define XEN_DOMCTL_SCHEDOP_getinfo 1 ++struct xen_domctl_scheduler_op { ++ uint32_t sched_id; /* XEN_SCHEDULER_* */ ++ uint32_t cmd; /* XEN_DOMCTL_SCHEDOP_* */ ++ union { ++ struct xen_domctl_sched_sedf { ++ uint64_aligned_t period; ++ uint64_aligned_t slice; ++ uint64_aligned_t latency; ++ uint32_t extratime; ++ uint32_t weight; ++ } sedf; ++ struct xen_domctl_sched_credit { ++ uint16_t weight; ++ uint16_t cap; ++ } credit; ++ } u; ++}; ++typedef struct xen_domctl_scheduler_op xen_domctl_scheduler_op_t; ++DEFINE_XEN_GUEST_HANDLE(xen_domctl_scheduler_op_t); ++ ++ ++/* XEN_DOMCTL_setdomainhandle */ ++struct xen_domctl_setdomainhandle { ++ xen_domain_handle_t handle; ++}; ++typedef struct xen_domctl_setdomainhandle xen_domctl_setdomainhandle_t; ++DEFINE_XEN_GUEST_HANDLE(xen_domctl_setdomainhandle_t); ++ ++ ++/* XEN_DOMCTL_setdebugging */ ++struct xen_domctl_setdebugging { ++ uint8_t enable; ++}; ++typedef struct xen_domctl_setdebugging xen_domctl_setdebugging_t; ++DEFINE_XEN_GUEST_HANDLE(xen_domctl_setdebugging_t); ++ ++ ++/* XEN_DOMCTL_irq_permission */ ++struct xen_domctl_irq_permission { ++ uint8_t pirq; ++ uint8_t allow_access; /* flag to specify enable/disable of IRQ access */ ++}; ++typedef struct xen_domctl_irq_permission xen_domctl_irq_permission_t; ++DEFINE_XEN_GUEST_HANDLE(xen_domctl_irq_permission_t); ++ ++ ++/* XEN_DOMCTL_iomem_permission */ ++struct xen_domctl_iomem_permission { ++ uint64_aligned_t first_mfn;/* first page (physical page number) in range */ ++ uint64_aligned_t nr_mfns; /* number of pages in range (>0) */ ++ uint8_t allow_access; /* allow (!0) or deny (0) access to range? */ ++}; ++typedef struct xen_domctl_iomem_permission xen_domctl_iomem_permission_t; ++DEFINE_XEN_GUEST_HANDLE(xen_domctl_iomem_permission_t); ++ ++ ++/* XEN_DOMCTL_ioport_permission */ ++struct xen_domctl_ioport_permission { ++ uint32_t first_port; /* first port int range */ ++ uint32_t nr_ports; /* size of port range */ ++ uint8_t allow_access; /* allow or deny access to range? */ ++}; ++typedef struct xen_domctl_ioport_permission xen_domctl_ioport_permission_t; ++DEFINE_XEN_GUEST_HANDLE(xen_domctl_ioport_permission_t); ++ ++ ++/* XEN_DOMCTL_hypercall_init */ ++struct xen_domctl_hypercall_init { ++ uint64_aligned_t gmfn; /* GMFN to be initialised */ ++}; ++typedef struct xen_domctl_hypercall_init xen_domctl_hypercall_init_t; ++DEFINE_XEN_GUEST_HANDLE(xen_domctl_hypercall_init_t); ++ ++ ++/* XEN_DOMCTL_arch_setup */ ++#define _XEN_DOMAINSETUP_hvm_guest 0 ++#define XEN_DOMAINSETUP_hvm_guest (1UL<<_XEN_DOMAINSETUP_hvm_guest) ++#define _XEN_DOMAINSETUP_query 1 /* Get parameters (for save) */ ++#define XEN_DOMAINSETUP_query (1UL<<_XEN_DOMAINSETUP_query) ++#define _XEN_DOMAINSETUP_sioemu_guest 2 ++#define XEN_DOMAINSETUP_sioemu_guest (1UL<<_XEN_DOMAINSETUP_sioemu_guest) ++typedef struct xen_domctl_arch_setup { ++ uint64_aligned_t flags; /* XEN_DOMAINSETUP_* */ ++#ifdef __ia64__ ++ uint64_aligned_t bp; /* mpaddr of boot param area */ ++ uint64_aligned_t maxmem; /* Highest memory address for MDT. */ ++ uint64_aligned_t xsi_va; /* Xen shared_info area virtual address. */ ++ uint32_t hypercall_imm; /* Break imm for Xen hypercalls. */ ++ int8_t vhpt_size_log2; /* Log2 of VHPT size. */ ++#endif ++} xen_domctl_arch_setup_t; ++DEFINE_XEN_GUEST_HANDLE(xen_domctl_arch_setup_t); ++ ++ ++/* XEN_DOMCTL_settimeoffset */ ++struct xen_domctl_settimeoffset { ++ int32_t time_offset_seconds; /* applied to domain wallclock time */ ++}; ++typedef struct xen_domctl_settimeoffset xen_domctl_settimeoffset_t; ++DEFINE_XEN_GUEST_HANDLE(xen_domctl_settimeoffset_t); ++ ++/* XEN_DOMCTL_gethvmcontext */ ++/* XEN_DOMCTL_sethvmcontext */ ++typedef struct xen_domctl_hvmcontext { ++ uint32_t size; /* IN/OUT: size of buffer / bytes filled */ ++ XEN_GUEST_HANDLE_64(uint8) buffer; /* IN/OUT: data, or call ++ * gethvmcontext with NULL ++ * buffer to get size req'd */ ++} xen_domctl_hvmcontext_t; ++DEFINE_XEN_GUEST_HANDLE(xen_domctl_hvmcontext_t); ++ ++ ++/* XEN_DOMCTL_set_address_size */ ++/* XEN_DOMCTL_get_address_size */ ++typedef struct xen_domctl_address_size { ++ uint32_t size; ++} xen_domctl_address_size_t; ++DEFINE_XEN_GUEST_HANDLE(xen_domctl_address_size_t); ++ ++ ++/* XEN_DOMCTL_real_mode_area */ ++struct xen_domctl_real_mode_area { ++ uint32_t log; /* log2 of Real Mode Area size */ ++}; ++typedef struct xen_domctl_real_mode_area xen_domctl_real_mode_area_t; ++DEFINE_XEN_GUEST_HANDLE(xen_domctl_real_mode_area_t); ++ ++ ++/* XEN_DOMCTL_sendtrigger */ ++#define XEN_DOMCTL_SENDTRIGGER_NMI 0 ++#define XEN_DOMCTL_SENDTRIGGER_RESET 1 ++#define XEN_DOMCTL_SENDTRIGGER_INIT 2 ++#define XEN_DOMCTL_SENDTRIGGER_POWER 3 ++struct xen_domctl_sendtrigger { ++ uint32_t trigger; /* IN */ ++ uint32_t vcpu; /* IN */ ++}; ++typedef struct xen_domctl_sendtrigger xen_domctl_sendtrigger_t; ++DEFINE_XEN_GUEST_HANDLE(xen_domctl_sendtrigger_t); ++ ++ ++/* Assign PCI device to HVM guest. Sets up IOMMU structures. */ ++/* XEN_DOMCTL_assign_device */ ++/* XEN_DOMCTL_test_assign_device */ ++/* XEN_DOMCTL_deassign_device */ ++struct xen_domctl_assign_device { ++ uint32_t machine_bdf; /* machine PCI ID of assigned device */ ++}; ++typedef struct xen_domctl_assign_device xen_domctl_assign_device_t; ++DEFINE_XEN_GUEST_HANDLE(xen_domctl_assign_device_t); ++ ++/* Retrieve sibling devices infomation of machine_bdf */ ++/* XEN_DOMCTL_get_device_group */ ++struct xen_domctl_get_device_group { ++ uint32_t machine_bdf; /* IN */ ++ uint32_t max_sdevs; /* IN */ ++ uint32_t num_sdevs; /* OUT */ ++ XEN_GUEST_HANDLE_64(uint32) sdev_array; /* OUT */ ++}; ++typedef struct xen_domctl_get_device_group xen_domctl_get_device_group_t; ++DEFINE_XEN_GUEST_HANDLE(xen_domctl_get_device_group_t); ++ ++/* Pass-through interrupts: bind real irq -> hvm devfn. */ ++/* XEN_DOMCTL_bind_pt_irq */ ++/* XEN_DOMCTL_unbind_pt_irq */ ++typedef enum pt_irq_type_e { ++ PT_IRQ_TYPE_PCI, ++ PT_IRQ_TYPE_ISA, ++ PT_IRQ_TYPE_MSI, ++ PT_IRQ_TYPE_MSI_TRANSLATE, ++} pt_irq_type_t; ++struct xen_domctl_bind_pt_irq { ++ uint32_t machine_irq; ++ pt_irq_type_t irq_type; ++ uint32_t hvm_domid; ++ ++ union { ++ struct { ++ uint8_t isa_irq; ++ } isa; ++ struct { ++ uint8_t bus; ++ uint8_t device; ++ uint8_t intx; ++ } pci; ++ struct { ++ uint8_t gvec; ++ uint32_t gflags; ++ uint64_aligned_t gtable; ++ } msi; ++ } u; ++}; ++typedef struct xen_domctl_bind_pt_irq xen_domctl_bind_pt_irq_t; ++DEFINE_XEN_GUEST_HANDLE(xen_domctl_bind_pt_irq_t); ++ ++ ++/* Bind machine I/O address range -> HVM address range. */ ++/* XEN_DOMCTL_memory_mapping */ ++#define DPCI_ADD_MAPPING 1 ++#define DPCI_REMOVE_MAPPING 0 ++struct xen_domctl_memory_mapping { ++ uint64_aligned_t first_gfn; /* first page (hvm guest phys page) in range */ ++ uint64_aligned_t first_mfn; /* first page (machine page) in range */ ++ uint64_aligned_t nr_mfns; /* number of pages in range (>0) */ ++ uint32_t add_mapping; /* add or remove mapping */ ++ uint32_t padding; /* padding for 64-bit aligned structure */ ++}; ++typedef struct xen_domctl_memory_mapping xen_domctl_memory_mapping_t; ++DEFINE_XEN_GUEST_HANDLE(xen_domctl_memory_mapping_t); ++ ++ ++/* Bind machine I/O port range -> HVM I/O port range. */ ++/* XEN_DOMCTL_ioport_mapping */ ++struct xen_domctl_ioport_mapping { ++ uint32_t first_gport; /* first guest IO port*/ ++ uint32_t first_mport; /* first machine IO port */ ++ uint32_t nr_ports; /* size of port range */ ++ uint32_t add_mapping; /* add or remove mapping */ ++}; ++typedef struct xen_domctl_ioport_mapping xen_domctl_ioport_mapping_t; ++DEFINE_XEN_GUEST_HANDLE(xen_domctl_ioport_mapping_t); ++ ++ ++/* ++ * Pin caching type of RAM space for x86 HVM domU. ++ */ ++/* XEN_DOMCTL_pin_mem_cacheattr */ ++/* Caching types: these happen to be the same as x86 MTRR/PAT type codes. */ ++#define XEN_DOMCTL_MEM_CACHEATTR_UC 0 ++#define XEN_DOMCTL_MEM_CACHEATTR_WC 1 ++#define XEN_DOMCTL_MEM_CACHEATTR_WT 4 ++#define XEN_DOMCTL_MEM_CACHEATTR_WP 5 ++#define XEN_DOMCTL_MEM_CACHEATTR_WB 6 ++#define XEN_DOMCTL_MEM_CACHEATTR_UCM 7 ++struct xen_domctl_pin_mem_cacheattr { ++ uint64_aligned_t start, end; ++ uint32_t type; /* XEN_DOMCTL_MEM_CACHEATTR_* */ ++}; ++typedef struct xen_domctl_pin_mem_cacheattr xen_domctl_pin_mem_cacheattr_t; ++DEFINE_XEN_GUEST_HANDLE(xen_domctl_pin_mem_cacheattr_t); ++ ++ ++/* XEN_DOMCTL_set_ext_vcpucontext */ ++/* XEN_DOMCTL_get_ext_vcpucontext */ ++struct xen_domctl_ext_vcpucontext { ++ /* IN: VCPU that this call applies to. */ ++ uint32_t vcpu; ++ /* ++ * SET: Size of struct (IN) ++ * GET: Size of struct (OUT) ++ */ ++ uint32_t size; ++#if defined(__i386__) || defined(__x86_64__) ++ /* SYSCALL from 32-bit mode and SYSENTER callback information. */ ++ /* NB. SYSCALL from 64-bit mode is contained in vcpu_guest_context_t */ ++ uint64_aligned_t syscall32_callback_eip; ++ uint64_aligned_t sysenter_callback_eip; ++ uint16_t syscall32_callback_cs; ++ uint16_t sysenter_callback_cs; ++ uint8_t syscall32_disables_events; ++ uint8_t sysenter_disables_events; ++#endif ++}; ++typedef struct xen_domctl_ext_vcpucontext xen_domctl_ext_vcpucontext_t; ++DEFINE_XEN_GUEST_HANDLE(xen_domctl_ext_vcpucontext_t); ++ ++/* ++ * Set optimizaton features for a domain ++ */ ++/* XEN_DOMCTL_set_opt_feature */ ++struct xen_domctl_set_opt_feature { ++#if defined(__ia64__) ++ struct xen_ia64_opt_feature optf; ++#else ++ /* Make struct non-empty: do not depend on this field name! */ ++ uint64_t dummy; ++#endif ++}; ++typedef struct xen_domctl_set_opt_feature xen_domctl_set_opt_feature_t; ++DEFINE_XEN_GUEST_HANDLE(xen_domctl_set_opt_feature_t); ++ ++/* ++ * Set the target domain for a domain ++ */ ++/* XEN_DOMCTL_set_target */ ++struct xen_domctl_set_target { ++ domid_t target; ++}; ++typedef struct xen_domctl_set_target xen_domctl_set_target_t; ++DEFINE_XEN_GUEST_HANDLE(xen_domctl_set_target_t); ++ ++#if defined(__i386__) || defined(__x86_64__) ++# define XEN_CPUID_INPUT_UNUSED 0xFFFFFFFF ++/* XEN_DOMCTL_set_cpuid */ ++struct xen_domctl_cpuid { ++ uint32_t input[2]; ++ uint32_t eax; ++ uint32_t ebx; ++ uint32_t ecx; ++ uint32_t edx; ++}; ++typedef struct xen_domctl_cpuid xen_domctl_cpuid_t; ++DEFINE_XEN_GUEST_HANDLE(xen_domctl_cpuid_t); ++#endif ++ ++/* XEN_DOMCTL_subscribe */ ++struct xen_domctl_subscribe { ++ uint32_t port; /* IN */ ++}; ++typedef struct xen_domctl_subscribe xen_domctl_subscribe_t; ++DEFINE_XEN_GUEST_HANDLE(xen_domctl_subscribe_t); ++ ++/* ++ * Define the maximum machine address size which should be allocated ++ * to a guest. ++ */ ++/* XEN_DOMCTL_set_machine_address_size */ ++/* XEN_DOMCTL_get_machine_address_size */ ++ ++/* ++ * Do not inject spurious page faults into this domain. ++ */ ++/* XEN_DOMCTL_suppress_spurious_page_faults */ ++ ++/* XEN_DOMCTL_debug_op */ ++#define XEN_DOMCTL_DEBUG_OP_SINGLE_STEP_OFF 0 ++#define XEN_DOMCTL_DEBUG_OP_SINGLE_STEP_ON 1 ++struct xen_domctl_debug_op { ++ uint32_t op; /* IN */ ++ uint32_t vcpu; /* IN */ ++}; ++typedef struct xen_domctl_debug_op xen_domctl_debug_op_t; ++DEFINE_XEN_GUEST_HANDLE(xen_domctl_debug_op_t); ++ ++/* ++ * Request a particular record from the HVM context ++ */ ++/* XEN_DOMCTL_gethvmcontext_partial */ ++typedef struct xen_domctl_hvmcontext_partial { ++ uint32_t type; /* IN: Type of record required */ ++ uint32_t instance; /* IN: Instance of that type */ ++ XEN_GUEST_HANDLE_64(uint8) buffer; /* OUT: buffer to write record into */ ++} xen_domctl_hvmcontext_partial_t; ++DEFINE_XEN_GUEST_HANDLE(xen_domctl_hvmcontext_partial_t); ++ ++/* XEN_DOMCTL_disable_migrate */ ++typedef struct xen_domctl_disable_migrate { ++ uint32_t disable; /* IN: 1: disable migration and restore */ ++} xen_domctl_disable_migrate_t; ++ ++ ++/* XEN_DOMCTL_gettscinfo */ ++/* XEN_DOMCTL_settscinfo */ ++struct xen_guest_tsc_info { ++ uint32_t tsc_mode; ++ uint32_t gtsc_khz; ++ uint32_t incarnation; ++ uint32_t pad; ++ uint64_aligned_t elapsed_nsec; ++}; ++typedef struct xen_guest_tsc_info xen_guest_tsc_info_t; ++DEFINE_XEN_GUEST_HANDLE(xen_guest_tsc_info_t); ++typedef struct xen_domctl_tsc_info { ++ XEN_GUEST_HANDLE_64(xen_guest_tsc_info_t) out_info; /* OUT */ ++ xen_guest_tsc_info_t info; /* IN */ ++} xen_domctl_tsc_info_t; ++ ++/* XEN_DOMCTL_gdbsx_guestmemio guest mem io */ ++struct xen_domctl_gdbsx_memio { ++ /* IN */ ++ uint64_aligned_t pgd3val;/* optional: init_mm.pgd[3] value */ ++ uint64_aligned_t gva; /* guest virtual address */ ++ uint64_aligned_t uva; /* user buffer virtual address */ ++ uint32_t len; /* number of bytes to read/write */ ++ uint8_t gwr; /* 0 = read from guest. 1 = write to guest */ ++ /* OUT */ ++ uint32_t remain; /* bytes remaining to be copied */ ++}; ++ ++/* XEN_DOMCTL_gdbsx_pausevcpu */ ++/* XEN_DOMCTL_gdbsx_unpausevcpu */ ++struct xen_domctl_gdbsx_pauseunp_vcpu { /* pause/unpause a vcpu */ ++ uint32_t vcpu; /* which vcpu */ ++}; ++ ++/* XEN_DOMCTL_gdbsx_domstatus */ ++struct xen_domctl_gdbsx_domstatus { ++ /* OUT */ ++ uint8_t paused; /* is the domain paused */ ++ uint32_t vcpu_id; /* any vcpu in an event? */ ++ uint32_t vcpu_ev; /* if yes, what event? */ ++}; ++ ++/* ++ * Memory event operations ++ */ ++ ++/* XEN_DOMCTL_mem_event_op */ ++ ++/* Add and remove memory handlers */ ++#define XEN_DOMCTL_MEM_EVENT_OP_ENABLE 0 ++#define XEN_DOMCTL_MEM_EVENT_OP_DISABLE 1 ++ ++/* ++ * Page memory in and out. ++ */ ++#define XEN_DOMCTL_MEM_EVENT_OP_PAGING (1 << 0) ++ ++/* Domain memory paging */ ++#define XEN_DOMCTL_MEM_EVENT_OP_PAGING_NOMINATE 0 ++#define XEN_DOMCTL_MEM_EVENT_OP_PAGING_EVICT 1 ++#define XEN_DOMCTL_MEM_EVENT_OP_PAGING_PREP 2 ++#define XEN_DOMCTL_MEM_EVENT_OP_PAGING_RESUME 3 ++ ++struct xen_domctl_mem_event_op { ++ uint32_t op; /* XEN_DOMCTL_MEM_EVENT_OP_* */ ++ uint32_t mode; /* XEN_DOMCTL_MEM_EVENT_ENABLE_* */ ++ ++ /* OP_ENABLE */ ++ uint64_aligned_t shared_addr; /* IN: Virtual address of shared page */ ++ uint64_aligned_t ring_addr; /* IN: Virtual address of ring page */ ++ ++ /* Other OPs */ ++ uint64_aligned_t gfn; /* IN: gfn of page being operated on */ ++}; ++typedef struct xen_domctl_mem_event_op xen_domctl_mem_event_op_t; ++DEFINE_XEN_GUEST_HANDLE(xen_domctl_mem_event_op_t); ++ ++/* ++ * Memory sharing operations ++ */ ++/* XEN_DOMCTL_mem_sharing_op */ ++ ++#define XEN_DOMCTL_MEM_SHARING_OP_CONTROL 0 ++#define XEN_DOMCTL_MEM_SHARING_OP_NOMINATE_GFN 1 ++#define XEN_DOMCTL_MEM_SHARING_OP_NOMINATE_GREF 2 ++#define XEN_DOMCTL_MEM_SHARING_OP_SHARE 3 ++#define XEN_DOMCTL_MEM_SHARING_OP_RESUME 4 ++#define XEN_DOMCTL_MEM_SHARING_OP_DEBUG_GFN 5 ++#define XEN_DOMCTL_MEM_SHARING_OP_DEBUG_MFN 6 ++#define XEN_DOMCTL_MEM_SHARING_OP_DEBUG_GREF 7 ++ ++#define XEN_DOMCTL_MEM_SHARING_S_HANDLE_INVALID (-10) ++#define XEN_DOMCTL_MEM_SHARING_C_HANDLE_INVALID (-9) ++ ++struct xen_domctl_mem_sharing_op { ++ uint8_t op; /* XEN_DOMCTL_MEM_EVENT_OP_* */ ++ ++ union { ++ uint8_t enable; /* OP_CONTROL */ ++ ++ struct mem_sharing_op_nominate { /* OP_NOMINATE_xxx */ ++ union { ++ uint64_aligned_t gfn; /* IN: gfn to nominate */ ++ uint32_t grant_ref; /* IN: grant ref to nominate */ ++ } u; ++ uint64_aligned_t handle; /* OUT: the handle */ ++ } nominate; ++ struct mem_sharing_op_share { /* OP_SHARE */ ++ uint64_aligned_t source_handle; /* IN: handle to the source page */ ++ uint64_aligned_t client_handle; /* IN: handle to the client page */ ++ } share; ++ struct mem_sharing_op_debug { /* OP_DEBUG_xxx */ ++ union { ++ uint64_aligned_t gfn; /* IN: gfn to debug */ ++ uint64_aligned_t mfn; /* IN: mfn to debug */ ++ grant_ref_t gref; /* IN: gref to debug */ ++ } u; ++ } debug; ++ } u; ++}; ++typedef struct xen_domctl_mem_sharing_op xen_domctl_mem_sharing_op_t; ++DEFINE_XEN_GUEST_HANDLE(xen_domctl_mem_sharing_op_t); ++ ++ ++struct xen_domctl { ++ uint32_t cmd; ++#define XEN_DOMCTL_createdomain 1 ++#define XEN_DOMCTL_destroydomain 2 ++#define XEN_DOMCTL_pausedomain 3 ++#define XEN_DOMCTL_unpausedomain 4 ++#define XEN_DOMCTL_getdomaininfo 5 ++#define XEN_DOMCTL_getmemlist 6 ++#define XEN_DOMCTL_getpageframeinfo 7 ++#define XEN_DOMCTL_getpageframeinfo2 8 ++#define XEN_DOMCTL_setvcpuaffinity 9 ++#define XEN_DOMCTL_shadow_op 10 ++#define XEN_DOMCTL_max_mem 11 ++#define XEN_DOMCTL_setvcpucontext 12 ++#define XEN_DOMCTL_getvcpucontext 13 ++#define XEN_DOMCTL_getvcpuinfo 14 ++#define XEN_DOMCTL_max_vcpus 15 ++#define XEN_DOMCTL_scheduler_op 16 ++#define XEN_DOMCTL_setdomainhandle 17 ++#define XEN_DOMCTL_setdebugging 18 ++#define XEN_DOMCTL_irq_permission 19 ++#define XEN_DOMCTL_iomem_permission 20 ++#define XEN_DOMCTL_ioport_permission 21 ++#define XEN_DOMCTL_hypercall_init 22 ++#define XEN_DOMCTL_arch_setup 23 ++#define XEN_DOMCTL_settimeoffset 24 ++#define XEN_DOMCTL_getvcpuaffinity 25 ++#define XEN_DOMCTL_real_mode_area 26 ++#define XEN_DOMCTL_resumedomain 27 ++#define XEN_DOMCTL_sendtrigger 28 ++#define XEN_DOMCTL_subscribe 29 ++#define XEN_DOMCTL_gethvmcontext 33 ++#define XEN_DOMCTL_sethvmcontext 34 ++#define XEN_DOMCTL_set_address_size 35 ++#define XEN_DOMCTL_get_address_size 36 ++#define XEN_DOMCTL_assign_device 37 ++#define XEN_DOMCTL_bind_pt_irq 38 ++#define XEN_DOMCTL_memory_mapping 39 ++#define XEN_DOMCTL_ioport_mapping 40 ++#define XEN_DOMCTL_pin_mem_cacheattr 41 ++#define XEN_DOMCTL_set_ext_vcpucontext 42 ++#define XEN_DOMCTL_get_ext_vcpucontext 43 ++#define XEN_DOMCTL_set_opt_feature 44 ++#define XEN_DOMCTL_test_assign_device 45 ++#define XEN_DOMCTL_set_target 46 ++#define XEN_DOMCTL_deassign_device 47 ++#define XEN_DOMCTL_unbind_pt_irq 48 ++#define XEN_DOMCTL_set_cpuid 49 ++#define XEN_DOMCTL_get_device_group 50 ++#define XEN_DOMCTL_set_machine_address_size 51 ++#define XEN_DOMCTL_get_machine_address_size 52 ++#define XEN_DOMCTL_suppress_spurious_page_faults 53 ++#define XEN_DOMCTL_debug_op 54 ++#define XEN_DOMCTL_gethvmcontext_partial 55 ++#define XEN_DOMCTL_mem_event_op 56 ++#define XEN_DOMCTL_mem_sharing_op 57 ++#define XEN_DOMCTL_disable_migrate 58 ++#define XEN_DOMCTL_gettscinfo 59 ++#define XEN_DOMCTL_settscinfo 60 ++#define XEN_DOMCTL_gdbsx_guestmemio 1000 ++#define XEN_DOMCTL_gdbsx_pausevcpu 1001 ++#define XEN_DOMCTL_gdbsx_unpausevcpu 1002 ++#define XEN_DOMCTL_gdbsx_domstatus 1003 ++ uint32_t interface_version; /* XEN_DOMCTL_INTERFACE_VERSION */ ++ domid_t domain; ++ union { ++ struct xen_domctl_createdomain createdomain; ++ struct xen_domctl_getdomaininfo getdomaininfo; ++ struct xen_domctl_getmemlist getmemlist; ++ struct xen_domctl_getpageframeinfo getpageframeinfo; ++ struct xen_domctl_getpageframeinfo2 getpageframeinfo2; ++ struct xen_domctl_vcpuaffinity vcpuaffinity; ++ struct xen_domctl_shadow_op shadow_op; ++ struct xen_domctl_max_mem max_mem; ++ struct xen_domctl_vcpucontext vcpucontext; ++ struct xen_domctl_getvcpuinfo getvcpuinfo; ++ struct xen_domctl_max_vcpus max_vcpus; ++ struct xen_domctl_scheduler_op scheduler_op; ++ struct xen_domctl_setdomainhandle setdomainhandle; ++ struct xen_domctl_setdebugging setdebugging; ++ struct xen_domctl_irq_permission irq_permission; ++ struct xen_domctl_iomem_permission iomem_permission; ++ struct xen_domctl_ioport_permission ioport_permission; ++ struct xen_domctl_hypercall_init hypercall_init; ++ struct xen_domctl_arch_setup arch_setup; ++ struct xen_domctl_settimeoffset settimeoffset; ++ struct xen_domctl_disable_migrate disable_migrate; ++ struct xen_domctl_tsc_info tsc_info; ++ struct xen_domctl_real_mode_area real_mode_area; ++ struct xen_domctl_hvmcontext hvmcontext; ++ struct xen_domctl_hvmcontext_partial hvmcontext_partial; ++ struct xen_domctl_address_size address_size; ++ struct xen_domctl_sendtrigger sendtrigger; ++ struct xen_domctl_get_device_group get_device_group; ++ struct xen_domctl_assign_device assign_device; ++ struct xen_domctl_bind_pt_irq bind_pt_irq; ++ struct xen_domctl_memory_mapping memory_mapping; ++ struct xen_domctl_ioport_mapping ioport_mapping; ++ struct xen_domctl_pin_mem_cacheattr pin_mem_cacheattr; ++ struct xen_domctl_ext_vcpucontext ext_vcpucontext; ++ struct xen_domctl_set_opt_feature set_opt_feature; ++ struct xen_domctl_set_target set_target; ++ struct xen_domctl_subscribe subscribe; ++ struct xen_domctl_debug_op debug_op; ++ struct xen_domctl_mem_event_op mem_event_op; ++ struct xen_domctl_mem_sharing_op mem_sharing_op; ++#if defined(__i386__) || defined(__x86_64__) ++ struct xen_domctl_cpuid cpuid; ++#endif ++ struct xen_domctl_gdbsx_memio gdbsx_guest_memio; ++ struct xen_domctl_gdbsx_pauseunp_vcpu gdbsx_pauseunp_vcpu; ++ struct xen_domctl_gdbsx_domstatus gdbsx_domstatus; ++ uint8_t pad[128]; ++ } u; ++}; ++typedef struct xen_domctl xen_domctl_t; ++DEFINE_XEN_GUEST_HANDLE(xen_domctl_t); ++ ++#endif /* __XEN_PUBLIC_DOMCTL_H__ */ ++ ++/* ++ * Local variables: ++ * mode: C ++ * c-set-style: "BSD" ++ * c-basic-offset: 4 ++ * tab-width: 4 ++ * indent-tabs-mode: nil ++ * End: ++ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/include/xen/interface/hvm/e820.h 2007-06-12 13:14:19.000000000 +0200 +@@ -0,0 +1,34 @@ ++ ++/* ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to ++ * deal in the Software without restriction, including without limitation the ++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ++ * DEALINGS IN THE SOFTWARE. ++ */ ++ ++#ifndef __XEN_PUBLIC_HVM_E820_H__ ++#define __XEN_PUBLIC_HVM_E820_H__ ++ ++/* E820 location in HVM virtual address space. */ ++#define HVM_E820_PAGE 0x00090000 ++#define HVM_E820_NR_OFFSET 0x000001E8 ++#define HVM_E820_OFFSET 0x000002D0 ++ ++#define HVM_BELOW_4G_RAM_END 0xF0000000 ++#define HVM_BELOW_4G_MMIO_START HVM_BELOW_4G_RAM_END ++#define HVM_BELOW_4G_MMIO_LENGTH ((1ULL << 32) - HVM_BELOW_4G_MMIO_START) ++ ++#endif /* __XEN_PUBLIC_HVM_E820_H__ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/include/xen/interface/hvm/hvm_info_table.h 2010-01-04 11:56:34.000000000 +0100 +@@ -0,0 +1,75 @@ ++/****************************************************************************** ++ * hvm/hvm_info_table.h ++ * ++ * HVM parameter and information table, written into guest memory map. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to ++ * deal in the Software without restriction, including without limitation the ++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ++ * DEALINGS IN THE SOFTWARE. ++ */ ++ ++#ifndef __XEN_PUBLIC_HVM_HVM_INFO_TABLE_H__ ++#define __XEN_PUBLIC_HVM_HVM_INFO_TABLE_H__ ++ ++#define HVM_INFO_PFN 0x09F ++#define HVM_INFO_OFFSET 0x800 ++#define HVM_INFO_PADDR ((HVM_INFO_PFN << 12) + HVM_INFO_OFFSET) ++ ++/* Maximum we can support with current vLAPIC ID mapping. */ ++#define HVM_MAX_VCPUS 128 ++ ++struct hvm_info_table { ++ char signature[8]; /* "HVM INFO" */ ++ uint32_t length; ++ uint8_t checksum; ++ ++ /* Should firmware build ACPI tables? */ ++ uint8_t acpi_enabled; ++ ++ /* Should firmware build APIC descriptors (APIC MADT / MP BIOS)? */ ++ uint8_t apic_mode; ++ ++ /* How many CPUs does this domain have? */ ++ uint32_t nr_vcpus; ++ ++ /* ++ * MEMORY MAP provided by HVM domain builder. ++ * Notes: ++ * 1. page_to_phys(x) = x << 12 ++ * 2. If a field is zero, the corresponding range does not exist. ++ */ ++ /* ++ * 0x0 to page_to_phys(low_mem_pgend)-1: ++ * RAM below 4GB (except for VGA hole 0xA0000-0xBFFFF) ++ */ ++ uint32_t low_mem_pgend; ++ /* ++ * page_to_phys(reserved_mem_pgstart) to 0xFFFFFFFF: ++ * Reserved for special memory mappings ++ */ ++ uint32_t reserved_mem_pgstart; ++ /* ++ * 0x100000000 to page_to_phys(high_mem_pgend)-1: ++ * RAM above 4GB ++ */ ++ uint32_t high_mem_pgend; ++ ++ /* Bitmap of which CPUs are online at boot time. */ ++ uint8_t vcpu_online[HVM_MAX_VCPUS/8]; ++}; ++ ++#endif /* __XEN_PUBLIC_HVM_HVM_INFO_TABLE_H__ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/include/xen/interface/hvm/hvm_op.h 2009-06-23 09:28:21.000000000 +0200 +@@ -0,0 +1,133 @@ ++/* ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to ++ * deal in the Software without restriction, including without limitation the ++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ++ * DEALINGS IN THE SOFTWARE. ++ */ ++ ++#ifndef __XEN_PUBLIC_HVM_HVM_OP_H__ ++#define __XEN_PUBLIC_HVM_HVM_OP_H__ ++ ++#include "../xen.h" ++ ++/* Get/set subcommands: extra argument == pointer to xen_hvm_param struct. */ ++#define HVMOP_set_param 0 ++#define HVMOP_get_param 1 ++struct xen_hvm_param { ++ domid_t domid; /* IN */ ++ uint32_t index; /* IN */ ++ uint64_t value; /* IN/OUT */ ++}; ++typedef struct xen_hvm_param xen_hvm_param_t; ++DEFINE_XEN_GUEST_HANDLE(xen_hvm_param_t); ++ ++/* Set the logical level of one of a domain's PCI INTx wires. */ ++#define HVMOP_set_pci_intx_level 2 ++struct xen_hvm_set_pci_intx_level { ++ /* Domain to be updated. */ ++ domid_t domid; ++ /* PCI INTx identification in PCI topology (domain:bus:device:intx). */ ++ uint8_t domain, bus, device, intx; ++ /* Assertion level (0 = unasserted, 1 = asserted). */ ++ uint8_t level; ++}; ++typedef struct xen_hvm_set_pci_intx_level xen_hvm_set_pci_intx_level_t; ++DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_pci_intx_level_t); ++ ++/* Set the logical level of one of a domain's ISA IRQ wires. */ ++#define HVMOP_set_isa_irq_level 3 ++struct xen_hvm_set_isa_irq_level { ++ /* Domain to be updated. */ ++ domid_t domid; ++ /* ISA device identification, by ISA IRQ (0-15). */ ++ uint8_t isa_irq; ++ /* Assertion level (0 = unasserted, 1 = asserted). */ ++ uint8_t level; ++}; ++typedef struct xen_hvm_set_isa_irq_level xen_hvm_set_isa_irq_level_t; ++DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_isa_irq_level_t); ++ ++#define HVMOP_set_pci_link_route 4 ++struct xen_hvm_set_pci_link_route { ++ /* Domain to be updated. */ ++ domid_t domid; ++ /* PCI link identifier (0-3). */ ++ uint8_t link; ++ /* ISA IRQ (1-15), or 0 (disable link). */ ++ uint8_t isa_irq; ++}; ++typedef struct xen_hvm_set_pci_link_route xen_hvm_set_pci_link_route_t; ++DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_pci_link_route_t); ++ ++/* Flushes all VCPU TLBs: @arg must be NULL. */ ++#define HVMOP_flush_tlbs 5 ++ ++/* Following tools-only interfaces may change in future. */ ++#if defined(__XEN__) || defined(__XEN_TOOLS__) ++ ++/* Track dirty VRAM. */ ++#define HVMOP_track_dirty_vram 6 ++struct xen_hvm_track_dirty_vram { ++ /* Domain to be tracked. */ ++ domid_t domid; ++ /* First pfn to track. */ ++ uint64_aligned_t first_pfn; ++ /* Number of pages to track. */ ++ uint64_aligned_t nr; ++ /* OUT variable. */ ++ /* Dirty bitmap buffer. */ ++ XEN_GUEST_HANDLE_64(uint8) dirty_bitmap; ++}; ++typedef struct xen_hvm_track_dirty_vram xen_hvm_track_dirty_vram_t; ++DEFINE_XEN_GUEST_HANDLE(xen_hvm_track_dirty_vram_t); ++ ++/* Notify that some pages got modified by the Device Model. */ ++#define HVMOP_modified_memory 7 ++struct xen_hvm_modified_memory { ++ /* Domain to be updated. */ ++ domid_t domid; ++ /* First pfn. */ ++ uint64_aligned_t first_pfn; ++ /* Number of pages. */ ++ uint64_aligned_t nr; ++}; ++typedef struct xen_hvm_modified_memory xen_hvm_modified_memory_t; ++DEFINE_XEN_GUEST_HANDLE(xen_hvm_modified_memory_t); ++ ++#define HVMOP_set_mem_type 8 ++typedef enum { ++ HVMMEM_ram_rw, /* Normal read/write guest RAM */ ++ HVMMEM_ram_ro, /* Read-only; writes are discarded */ ++ HVMMEM_mmio_dm, /* Reads and write go to the device model */ ++} hvmmem_type_t; ++/* Notify that a region of memory is to be treated in a specific way. */ ++struct xen_hvm_set_mem_type { ++ /* Domain to be updated. */ ++ domid_t domid; ++ /* Memory type */ ++ hvmmem_type_t hvmmem_type; ++ /* First pfn. */ ++ uint64_aligned_t first_pfn; ++ /* Number of pages. */ ++ uint64_aligned_t nr; ++}; ++typedef struct xen_hvm_set_mem_type xen_hvm_set_mem_type_t; ++DEFINE_XEN_GUEST_HANDLE(xen_hvm_set_mem_type_t); ++ ++ ++#endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */ ++ ++#endif /* __XEN_PUBLIC_HVM_HVM_OP_H__ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/include/xen/interface/hvm/ioreq.h 2010-01-04 11:56:34.000000000 +0100 +@@ -0,0 +1,119 @@ ++/* ++ * ioreq.h: I/O request definitions for device models ++ * Copyright (c) 2004, Intel Corporation. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to ++ * deal in the Software without restriction, including without limitation the ++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ++ * DEALINGS IN THE SOFTWARE. ++ */ ++ ++#ifndef _IOREQ_H_ ++#define _IOREQ_H_ ++ ++#define IOREQ_READ 1 ++#define IOREQ_WRITE 0 ++ ++#define STATE_IOREQ_NONE 0 ++#define STATE_IOREQ_READY 1 ++#define STATE_IOREQ_INPROCESS 2 ++#define STATE_IORESP_READY 3 ++ ++#define IOREQ_TYPE_PIO 0 /* pio */ ++#define IOREQ_TYPE_COPY 1 /* mmio ops */ ++#define IOREQ_TYPE_TIMEOFFSET 7 ++#define IOREQ_TYPE_INVALIDATE 8 /* mapcache */ ++ ++/* ++ * VMExit dispatcher should cooperate with instruction decoder to ++ * prepare this structure and notify service OS and DM by sending ++ * virq ++ */ ++struct ioreq { ++ uint64_t addr; /* physical address */ ++ uint64_t data; /* data (or paddr of data) */ ++ uint32_t count; /* for rep prefixes */ ++ uint32_t size; /* size in bytes */ ++ uint32_t vp_eport; /* evtchn for notifications to/from device model */ ++ uint16_t _pad0; ++ uint8_t state:4; ++ uint8_t data_is_ptr:1; /* if 1, data above is the guest paddr ++ * of the real data to use. */ ++ uint8_t dir:1; /* 1=read, 0=write */ ++ uint8_t df:1; ++ uint8_t _pad1:1; ++ uint8_t type; /* I/O type */ ++}; ++typedef struct ioreq ioreq_t; ++ ++struct shared_iopage { ++ struct ioreq vcpu_ioreq[1]; ++}; ++typedef struct shared_iopage shared_iopage_t; ++ ++struct buf_ioreq { ++ uint8_t type; /* I/O type */ ++ uint8_t pad:1; ++ uint8_t dir:1; /* 1=read, 0=write */ ++ uint8_t size:2; /* 0=>1, 1=>2, 2=>4, 3=>8. If 8, use two buf_ioreqs */ ++ uint32_t addr:20;/* physical address */ ++ uint32_t data; /* data */ ++}; ++typedef struct buf_ioreq buf_ioreq_t; ++ ++#define IOREQ_BUFFER_SLOT_NUM 511 /* 8 bytes each, plus 2 4-byte indexes */ ++struct buffered_iopage { ++ unsigned int read_pointer; ++ unsigned int write_pointer; ++ buf_ioreq_t buf_ioreq[IOREQ_BUFFER_SLOT_NUM]; ++}; /* NB. Size of this structure must be no greater than one page. */ ++typedef struct buffered_iopage buffered_iopage_t; ++ ++#if defined(__ia64__) ++struct pio_buffer { ++ uint32_t page_offset; ++ uint32_t pointer; ++ uint32_t data_end; ++ uint32_t buf_size; ++ void *opaque; ++}; ++ ++#define PIO_BUFFER_IDE_PRIMARY 0 /* I/O port = 0x1F0 */ ++#define PIO_BUFFER_IDE_SECONDARY 1 /* I/O port = 0x170 */ ++#define PIO_BUFFER_ENTRY_NUM 2 ++struct buffered_piopage { ++ struct pio_buffer pio[PIO_BUFFER_ENTRY_NUM]; ++ uint8_t buffer[1]; ++}; ++#endif /* defined(__ia64__) */ ++ ++#define ACPI_PM1A_EVT_BLK_ADDRESS 0x0000000000001f40 ++#define ACPI_PM1A_CNT_BLK_ADDRESS (ACPI_PM1A_EVT_BLK_ADDRESS + 0x04) ++#define ACPI_PM_TMR_BLK_ADDRESS (ACPI_PM1A_EVT_BLK_ADDRESS + 0x08) ++#define ACPI_GPE0_BLK_ADDRESS (ACPI_PM_TMR_BLK_ADDRESS + 0x20) ++#define ACPI_GPE0_BLK_LEN 0x08 ++ ++#endif /* _IOREQ_H_ */ ++ ++/* ++ * Local variables: ++ * mode: C ++ * c-set-style: "BSD" ++ * c-basic-offset: 4 ++ * tab-width: 4 ++ * indent-tabs-mode: nil ++ * End: ++ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/include/xen/interface/hvm/params.h 2009-04-07 13:58:49.000000000 +0200 +@@ -0,0 +1,111 @@ ++/* ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to ++ * deal in the Software without restriction, including without limitation the ++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ++ * DEALINGS IN THE SOFTWARE. ++ */ ++ ++#ifndef __XEN_PUBLIC_HVM_PARAMS_H__ ++#define __XEN_PUBLIC_HVM_PARAMS_H__ ++ ++#include "hvm_op.h" ++ ++/* ++ * Parameter space for HVMOP_{set,get}_param. ++ */ ++ ++/* ++ * How should CPU0 event-channel notifications be delivered? ++ * val[63:56] == 0: val[55:0] is a delivery GSI (Global System Interrupt). ++ * val[63:56] == 1: val[55:0] is a delivery PCI INTx line, as follows: ++ * Domain = val[47:32], Bus = val[31:16], ++ * DevFn = val[15: 8], IntX = val[ 1: 0] ++ * If val == 0 then CPU0 event-channel notifications are not delivered. ++ */ ++#define HVM_PARAM_CALLBACK_IRQ 0 ++ ++/* ++ * These are not used by Xen. They are here for convenience of HVM-guest ++ * xenbus implementations. ++ */ ++#define HVM_PARAM_STORE_PFN 1 ++#define HVM_PARAM_STORE_EVTCHN 2 ++ ++#define HVM_PARAM_PAE_ENABLED 4 ++ ++#define HVM_PARAM_IOREQ_PFN 5 ++ ++#define HVM_PARAM_BUFIOREQ_PFN 6 ++ ++#ifdef __ia64__ ++ ++#define HVM_PARAM_NVRAM_FD 7 ++#define HVM_PARAM_VHPT_SIZE 8 ++#define HVM_PARAM_BUFPIOREQ_PFN 9 ++ ++#elif defined(__i386__) || defined(__x86_64__) ++ ++/* Expose Viridian interfaces to this HVM guest? */ ++#define HVM_PARAM_VIRIDIAN 9 ++ ++#endif ++ ++/* ++ * Set mode for virtual timers (currently x86 only): ++ * delay_for_missed_ticks (default): ++ * Do not advance a vcpu's time beyond the correct delivery time for ++ * interrupts that have been missed due to preemption. Deliver missed ++ * interrupts when the vcpu is rescheduled and advance the vcpu's virtual ++ * time stepwise for each one. ++ * no_delay_for_missed_ticks: ++ * As above, missed interrupts are delivered, but guest time always tracks ++ * wallclock (i.e., real) time while doing so. ++ * no_missed_ticks_pending: ++ * No missed interrupts are held pending. Instead, to ensure ticks are ++ * delivered at some non-zero rate, if we detect missed ticks then the ++ * internal tick alarm is not disabled if the VCPU is preempted during the ++ * next tick period. ++ * one_missed_tick_pending: ++ * Missed interrupts are collapsed together and delivered as one 'late tick'. ++ * Guest time always tracks wallclock (i.e., real) time. ++ */ ++#define HVM_PARAM_TIMER_MODE 10 ++#define HVMPTM_delay_for_missed_ticks 0 ++#define HVMPTM_no_delay_for_missed_ticks 1 ++#define HVMPTM_no_missed_ticks_pending 2 ++#define HVMPTM_one_missed_tick_pending 3 ++ ++/* Boolean: Enable virtual HPET (high-precision event timer)? (x86-only) */ ++#define HVM_PARAM_HPET_ENABLED 11 ++ ++/* Identity-map page directory used by Intel EPT when CR0.PG=0. */ ++#define HVM_PARAM_IDENT_PT 12 ++ ++/* Device Model domain, defaults to 0. */ ++#define HVM_PARAM_DM_DOMAIN 13 ++ ++/* ACPI S state: currently support S0 and S3 on x86. */ ++#define HVM_PARAM_ACPI_S_STATE 14 ++ ++/* TSS used on Intel when CR0.PE=0. */ ++#define HVM_PARAM_VM86_TSS 15 ++ ++/* Boolean: Enable aligning all periodic vpts to reduce interrupts */ ++#define HVM_PARAM_VPT_ALIGN 16 ++ ++#define HVM_NR_PARAMS 17 ++ ++#endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/include/xen/interface/hvm/save.h 2008-04-02 12:34:02.000000000 +0200 +@@ -0,0 +1,88 @@ ++/* ++ * hvm/save.h ++ * ++ * Structure definitions for HVM state that is held by Xen and must ++ * be saved along with the domain's memory and device-model state. ++ * ++ * Copyright (c) 2007 XenSource Ltd. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to ++ * deal in the Software without restriction, including without limitation the ++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ++ * DEALINGS IN THE SOFTWARE. ++ */ ++ ++#ifndef __XEN_PUBLIC_HVM_SAVE_H__ ++#define __XEN_PUBLIC_HVM_SAVE_H__ ++ ++/* ++ * Structures in this header *must* have the same layout in 32bit ++ * and 64bit environments: this means that all fields must be explicitly ++ * sized types and aligned to their sizes, and the structs must be ++ * a multiple of eight bytes long. ++ * ++ * Only the state necessary for saving and restoring (i.e. fields ++ * that are analogous to actual hardware state) should go in this file. ++ * Internal mechanisms should be kept in Xen-private headers. ++ */ ++ ++#if !defined(__GNUC__) || defined(__STRICT_ANSI__) ++#error "Anonymous structs/unions are a GNU extension." ++#endif ++ ++/* ++ * Each entry is preceded by a descriptor giving its type and length ++ */ ++struct hvm_save_descriptor { ++ uint16_t typecode; /* Used to demux the various types below */ ++ uint16_t instance; /* Further demux within a type */ ++ uint32_t length; /* In bytes, *not* including this descriptor */ ++}; ++ ++ ++/* ++ * Each entry has a datatype associated with it: for example, the CPU state ++ * is saved as a HVM_SAVE_TYPE(CPU), which has HVM_SAVE_LENGTH(CPU), ++ * and is identified by a descriptor with typecode HVM_SAVE_CODE(CPU). ++ * DECLARE_HVM_SAVE_TYPE binds these things together with some type-system ++ * ugliness. ++ */ ++ ++#define DECLARE_HVM_SAVE_TYPE(_x, _code, _type) \ ++ struct __HVM_SAVE_TYPE_##_x { _type t; char c[_code]; } ++ ++#define HVM_SAVE_TYPE(_x) typeof (((struct __HVM_SAVE_TYPE_##_x *)(0))->t) ++#define HVM_SAVE_LENGTH(_x) (sizeof (HVM_SAVE_TYPE(_x))) ++#define HVM_SAVE_CODE(_x) (sizeof (((struct __HVM_SAVE_TYPE_##_x *)(0))->c)) ++ ++ ++/* ++ * The series of save records is teminated by a zero-type, zero-length ++ * descriptor. ++ */ ++ ++struct hvm_save_end {}; ++DECLARE_HVM_SAVE_TYPE(END, 0, struct hvm_save_end); ++ ++#if defined(__i386__) || defined(__x86_64__) ++#include "../arch-x86/hvm/save.h" ++#elif defined(__ia64__) ++#include "../arch-ia64/hvm/save.h" ++#else ++#error "unsupported architecture" ++#endif ++ ++#endif /* __XEN_PUBLIC_HVM_SAVE_H__ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/include/xen/interface/io/fsif.h 2009-06-23 09:28:21.000000000 +0200 +@@ -0,0 +1,192 @@ ++/****************************************************************************** ++ * fsif.h ++ * ++ * Interface to FS level split device drivers. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to ++ * deal in the Software without restriction, including without limitation the ++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ++ * DEALINGS IN THE SOFTWARE. ++ * ++ * Copyright (c) 2007, Grzegorz Milos, . ++ */ ++ ++#ifndef __XEN_PUBLIC_IO_FSIF_H__ ++#define __XEN_PUBLIC_IO_FSIF_H__ ++ ++#include "ring.h" ++#include "../grant_table.h" ++ ++#define REQ_FILE_OPEN 1 ++#define REQ_FILE_CLOSE 2 ++#define REQ_FILE_READ 3 ++#define REQ_FILE_WRITE 4 ++#define REQ_STAT 5 ++#define REQ_FILE_TRUNCATE 6 ++#define REQ_REMOVE 7 ++#define REQ_RENAME 8 ++#define REQ_CREATE 9 ++#define REQ_DIR_LIST 10 ++#define REQ_CHMOD 11 ++#define REQ_FS_SPACE 12 ++#define REQ_FILE_SYNC 13 ++ ++struct fsif_open_request { ++ grant_ref_t gref; ++}; ++ ++struct fsif_close_request { ++ uint32_t fd; ++}; ++ ++struct fsif_read_request { ++ uint32_t fd; ++ int32_t pad; ++ uint64_t len; ++ uint64_t offset; ++ grant_ref_t grefs[1]; /* Variable length */ ++}; ++ ++struct fsif_write_request { ++ uint32_t fd; ++ int32_t pad; ++ uint64_t len; ++ uint64_t offset; ++ grant_ref_t grefs[1]; /* Variable length */ ++}; ++ ++struct fsif_stat_request { ++ uint32_t fd; ++}; ++ ++/* This structure is a copy of some fields from stat structure, returned ++ * via the ring. */ ++struct fsif_stat_response { ++ int32_t stat_mode; ++ uint32_t stat_uid; ++ uint32_t stat_gid; ++ int32_t stat_ret; ++ int64_t stat_size; ++ int64_t stat_atime; ++ int64_t stat_mtime; ++ int64_t stat_ctime; ++}; ++ ++struct fsif_truncate_request { ++ uint32_t fd; ++ int32_t pad; ++ int64_t length; ++}; ++ ++struct fsif_remove_request { ++ grant_ref_t gref; ++}; ++ ++struct fsif_rename_request { ++ uint16_t old_name_offset; ++ uint16_t new_name_offset; ++ grant_ref_t gref; ++}; ++ ++struct fsif_create_request { ++ int8_t directory; ++ int8_t pad; ++ int16_t pad2; ++ int32_t mode; ++ grant_ref_t gref; ++}; ++ ++struct fsif_list_request { ++ uint32_t offset; ++ grant_ref_t gref; ++}; ++ ++#define NR_FILES_SHIFT 0 ++#define NR_FILES_SIZE 16 /* 16 bits for the number of files mask */ ++#define NR_FILES_MASK (((1ULL << NR_FILES_SIZE) - 1) << NR_FILES_SHIFT) ++#define ERROR_SIZE 32 /* 32 bits for the error mask */ ++#define ERROR_SHIFT (NR_FILES_SIZE + NR_FILES_SHIFT) ++#define ERROR_MASK (((1ULL << ERROR_SIZE) - 1) << ERROR_SHIFT) ++#define HAS_MORE_SHIFT (ERROR_SHIFT + ERROR_SIZE) ++#define HAS_MORE_FLAG (1ULL << HAS_MORE_SHIFT) ++ ++struct fsif_chmod_request { ++ uint32_t fd; ++ int32_t mode; ++}; ++ ++struct fsif_space_request { ++ grant_ref_t gref; ++}; ++ ++struct fsif_sync_request { ++ uint32_t fd; ++}; ++ ++ ++/* FS operation request */ ++struct fsif_request { ++ uint8_t type; /* Type of the request */ ++ uint8_t pad; ++ uint16_t id; /* Request ID, copied to the response */ ++ uint32_t pad2; ++ union { ++ struct fsif_open_request fopen; ++ struct fsif_close_request fclose; ++ struct fsif_read_request fread; ++ struct fsif_write_request fwrite; ++ struct fsif_stat_request fstat; ++ struct fsif_truncate_request ftruncate; ++ struct fsif_remove_request fremove; ++ struct fsif_rename_request frename; ++ struct fsif_create_request fcreate; ++ struct fsif_list_request flist; ++ struct fsif_chmod_request fchmod; ++ struct fsif_space_request fspace; ++ struct fsif_sync_request fsync; ++ } u; ++}; ++typedef struct fsif_request fsif_request_t; ++ ++/* FS operation response */ ++struct fsif_response { ++ uint16_t id; ++ uint16_t pad1; ++ uint32_t pad2; ++ union { ++ uint64_t ret_val; ++ struct fsif_stat_response fstat; ++ } u; ++}; ++ ++typedef struct fsif_response fsif_response_t; ++ ++#define FSIF_RING_ENTRY_SIZE 64 ++ ++#define FSIF_NR_READ_GNTS ((FSIF_RING_ENTRY_SIZE - sizeof(struct fsif_read_request)) / \ ++ sizeof(grant_ref_t) + 1) ++#define FSIF_NR_WRITE_GNTS ((FSIF_RING_ENTRY_SIZE - sizeof(struct fsif_write_request)) / \ ++ sizeof(grant_ref_t) + 1) ++ ++DEFINE_RING_TYPES(fsif, struct fsif_request, struct fsif_response); ++ ++#define STATE_INITIALISED "init" ++#define STATE_READY "ready" ++#define STATE_CLOSING "closing" ++#define STATE_CLOSED "closed" ++ ++ ++#endif +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/include/xen/interface/io/pciif.h 2009-04-07 13:58:49.000000000 +0200 +@@ -0,0 +1,124 @@ ++/* ++ * PCI Backend/Frontend Common Data Structures & Macros ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to ++ * deal in the Software without restriction, including without limitation the ++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ++ * DEALINGS IN THE SOFTWARE. ++ * ++ * Author: Ryan Wilson ++ */ ++#ifndef __XEN_PCI_COMMON_H__ ++#define __XEN_PCI_COMMON_H__ ++ ++/* Be sure to bump this number if you change this file */ ++#define XEN_PCI_MAGIC "7" ++ ++/* xen_pci_sharedinfo flags */ ++#define _XEN_PCIF_active (0) ++#define XEN_PCIF_active (1<<_XEN_PCIF_active) ++#define _XEN_PCIB_AERHANDLER (1) ++#define XEN_PCIB_AERHANDLER (1<<_XEN_PCIB_AERHANDLER) ++#define _XEN_PCIB_active (2) ++#define XEN_PCIB_active (1<<_XEN_PCIB_active) ++ ++/* xen_pci_op commands */ ++#define XEN_PCI_OP_conf_read (0) ++#define XEN_PCI_OP_conf_write (1) ++#define XEN_PCI_OP_enable_msi (2) ++#define XEN_PCI_OP_disable_msi (3) ++#define XEN_PCI_OP_enable_msix (4) ++#define XEN_PCI_OP_disable_msix (5) ++#define XEN_PCI_OP_aer_detected (6) ++#define XEN_PCI_OP_aer_resume (7) ++#define XEN_PCI_OP_aer_mmio (8) ++#define XEN_PCI_OP_aer_slotreset (9) ++ ++/* xen_pci_op error numbers */ ++#define XEN_PCI_ERR_success (0) ++#define XEN_PCI_ERR_dev_not_found (-1) ++#define XEN_PCI_ERR_invalid_offset (-2) ++#define XEN_PCI_ERR_access_denied (-3) ++#define XEN_PCI_ERR_not_implemented (-4) ++/* XEN_PCI_ERR_op_failed - backend failed to complete the operation */ ++#define XEN_PCI_ERR_op_failed (-5) ++ ++/* ++ * it should be PAGE_SIZE-sizeof(struct xen_pci_op))/sizeof(struct msix_entry)) ++ * Should not exceed 128 ++ */ ++#define SH_INFO_MAX_VEC 128 ++ ++struct xen_msix_entry { ++ uint16_t vector; ++ uint16_t entry; ++}; ++struct xen_pci_op { ++ /* IN: what action to perform: XEN_PCI_OP_* */ ++ uint32_t cmd; ++ ++ /* OUT: will contain an error number (if any) from errno.h */ ++ int32_t err; ++ ++ /* IN: which device to touch */ ++ uint32_t domain; /* PCI Domain/Segment */ ++ uint32_t bus; ++ uint32_t devfn; ++ ++ /* IN: which configuration registers to touch */ ++ int32_t offset; ++ int32_t size; ++ ++ /* IN/OUT: Contains the result after a READ or the value to WRITE */ ++ uint32_t value; ++ /* IN: Contains extra infor for this operation */ ++ uint32_t info; ++ /*IN: param for msi-x */ ++ struct xen_msix_entry msix_entries[SH_INFO_MAX_VEC]; ++}; ++ ++/*used for pcie aer handling*/ ++struct xen_pcie_aer_op ++{ ++ ++ /* IN: what action to perform: XEN_PCI_OP_* */ ++ uint32_t cmd; ++ /*IN/OUT: return aer_op result or carry error_detected state as input*/ ++ int32_t err; ++ ++ /* IN: which device to touch */ ++ uint32_t domain; /* PCI Domain/Segment*/ ++ uint32_t bus; ++ uint32_t devfn; ++}; ++struct xen_pci_sharedinfo { ++ /* flags - XEN_PCIF_* */ ++ uint32_t flags; ++ struct xen_pci_op op; ++ struct xen_pcie_aer_op aer_op; ++}; ++ ++#endif /* __XEN_PCI_COMMON_H__ */ ++ ++/* ++ * Local variables: ++ * mode: C ++ * c-set-style: "BSD" ++ * c-basic-offset: 4 ++ * tab-width: 4 ++ * indent-tabs-mode: nil ++ * End: ++ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/include/xen/interface/io/tpmif.h 2007-06-12 13:14:19.000000000 +0200 +@@ -0,0 +1,77 @@ ++/****************************************************************************** ++ * tpmif.h ++ * ++ * TPM I/O interface for Xen guest OSes. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to ++ * deal in the Software without restriction, including without limitation the ++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ++ * DEALINGS IN THE SOFTWARE. ++ * ++ * Copyright (c) 2005, IBM Corporation ++ * ++ * Author: Stefan Berger, stefanb@us.ibm.com ++ * Grant table support: Mahadevan Gomathisankaran ++ * ++ * This code has been derived from tools/libxc/xen/io/netif.h ++ * ++ * Copyright (c) 2003-2004, Keir Fraser ++ */ ++ ++#ifndef __XEN_PUBLIC_IO_TPMIF_H__ ++#define __XEN_PUBLIC_IO_TPMIF_H__ ++ ++#include "../grant_table.h" ++ ++struct tpmif_tx_request { ++ unsigned long addr; /* Machine address of packet. */ ++ grant_ref_t ref; /* grant table access reference */ ++ uint16_t unused; ++ uint16_t size; /* Packet size in bytes. */ ++}; ++typedef struct tpmif_tx_request tpmif_tx_request_t; ++ ++/* ++ * The TPMIF_TX_RING_SIZE defines the number of pages the ++ * front-end and backend can exchange (= size of array). ++ */ ++typedef uint32_t TPMIF_RING_IDX; ++ ++#define TPMIF_TX_RING_SIZE 1 ++ ++/* This structure must fit in a memory page. */ ++ ++struct tpmif_ring { ++ struct tpmif_tx_request req; ++}; ++typedef struct tpmif_ring tpmif_ring_t; ++ ++struct tpmif_tx_interface { ++ struct tpmif_ring ring[TPMIF_TX_RING_SIZE]; ++}; ++typedef struct tpmif_tx_interface tpmif_tx_interface_t; ++ ++#endif ++ ++/* ++ * Local variables: ++ * mode: C ++ * c-set-style: "BSD" ++ * c-basic-offset: 4 ++ * tab-width: 4 ++ * indent-tabs-mode: nil ++ * End: ++ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/include/xen/interface/io/usbif.h 2010-03-01 14:03:37.000000000 +0100 +@@ -0,0 +1,151 @@ ++/* ++ * usbif.h ++ * ++ * USB I/O interface for Xen guest OSes. ++ * ++ * Copyright (C) 2009, FUJITSU LABORATORIES LTD. ++ * Author: Noboru Iwamatsu ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to ++ * deal in the Software without restriction, including without limitation the ++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ++ * DEALINGS IN THE SOFTWARE. ++ */ ++ ++#ifndef __XEN_PUBLIC_IO_USBIF_H__ ++#define __XEN_PUBLIC_IO_USBIF_H__ ++ ++#include "ring.h" ++#include "../grant_table.h" ++ ++enum usb_spec_version { ++ USB_VER_UNKNOWN = 0, ++ USB_VER_USB11, ++ USB_VER_USB20, ++ USB_VER_USB30, /* not supported yet */ ++}; ++ ++/* ++ * USB pipe in usbif_request ++ * ++ * bits 0-5 are specific bits for virtual USB driver. ++ * bits 7-31 are standard urb pipe. ++ * ++ * - port number(NEW): bits 0-4 ++ * (USB_MAXCHILDREN is 31) ++ * ++ * - operation flag(NEW): bit 5 ++ * (0 = submit urb, ++ * 1 = unlink urb) ++ * ++ * - direction: bit 7 ++ * (0 = Host-to-Device [Out] ++ * 1 = Device-to-Host [In]) ++ * ++ * - device address: bits 8-14 ++ * ++ * - endpoint: bits 15-18 ++ * ++ * - pipe type: bits 30-31 ++ * (00 = isochronous, 01 = interrupt, ++ * 10 = control, 11 = bulk) ++ */ ++#define usbif_pipeportnum(pipe) ((pipe) & 0x1f) ++#define usbif_setportnum_pipe(pipe, portnum) \ ++ ((pipe)|(portnum)) ++ ++#define usbif_pipeunlink(pipe) ((pipe) & 0x20) ++#define usbif_pipesubmit(pipe) (!usbif_pipeunlink(pipe)) ++#define usbif_setunlink_pipe(pipe) ((pipe)|(0x20)) ++ ++#define USBIF_BACK_MAX_PENDING_REQS (128) ++#define USBIF_MAX_SEGMENTS_PER_REQUEST (16) ++ ++/* ++ * RING for transferring urbs. ++ */ ++struct usbif_request_segment { ++ grant_ref_t gref; ++ uint16_t offset; ++ uint16_t length; ++}; ++ ++struct usbif_urb_request { ++ uint16_t id; /* request id */ ++ uint16_t nr_buffer_segs; /* number of urb->transfer_buffer segments */ ++ ++ /* basic urb parameter */ ++ uint32_t pipe; ++ uint16_t transfer_flags; ++ uint16_t buffer_length; ++ union { ++ uint8_t ctrl[8]; /* setup_packet (Ctrl) */ ++ ++ struct { ++ uint16_t interval; /* maximum (1024*8) in usb core */ ++ uint16_t start_frame; /* start frame */ ++ uint16_t number_of_packets; /* number of ISO packet */ ++ uint16_t nr_frame_desc_segs; /* number of iso_frame_desc segments */ ++ } isoc; ++ ++ struct { ++ uint16_t interval; /* maximum (1024*8) in usb core */ ++ uint16_t pad[3]; ++ } intr; ++ ++ struct { ++ uint16_t unlink_id; /* unlink request id */ ++ uint16_t pad[3]; ++ } unlink; ++ ++ } u; ++ ++ /* urb data segments */ ++ struct usbif_request_segment seg[USBIF_MAX_SEGMENTS_PER_REQUEST]; ++}; ++typedef struct usbif_urb_request usbif_urb_request_t; ++ ++struct usbif_urb_response { ++ uint16_t id; /* request id */ ++ uint16_t start_frame; /* start frame (ISO) */ ++ int32_t status; /* status (non-ISO) */ ++ int32_t actual_length; /* actual transfer length */ ++ int32_t error_count; /* number of ISO errors */ ++}; ++typedef struct usbif_urb_response usbif_urb_response_t; ++ ++DEFINE_RING_TYPES(usbif_urb, struct usbif_urb_request, struct usbif_urb_response); ++#define USB_URB_RING_SIZE __CONST_RING_SIZE(usbif_urb, PAGE_SIZE) ++ ++/* ++ * RING for notifying connect/disconnect events to frontend ++ */ ++struct usbif_conn_request { ++ uint16_t id; ++}; ++typedef struct usbif_conn_request usbif_conn_request_t; ++ ++struct usbif_conn_response { ++ uint16_t id; /* request id */ ++ uint8_t portnum; /* port number */ ++ uint8_t speed; /* usb_device_speed */ ++}; ++typedef struct usbif_conn_response usbif_conn_response_t; ++ ++DEFINE_RING_TYPES(usbif_conn, struct usbif_conn_request, struct usbif_conn_response); ++#define USB_CONN_RING_SIZE __CONST_RING_SIZE(usbif_conn, PAGE_SIZE) ++ ++#endif /* __XEN_PUBLIC_IO_USBIF_H__ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/include/xen/interface/io/vscsiif.h 2008-07-21 11:00:33.000000000 +0200 +@@ -0,0 +1,105 @@ ++/****************************************************************************** ++ * vscsiif.h ++ * ++ * Based on the blkif.h code. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to ++ * deal in the Software without restriction, including without limitation the ++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ++ * DEALINGS IN THE SOFTWARE. ++ * ++ * Copyright(c) FUJITSU Limited 2008. ++ */ ++ ++#ifndef __XEN__PUBLIC_IO_SCSI_H__ ++#define __XEN__PUBLIC_IO_SCSI_H__ ++ ++#include "ring.h" ++#include "../grant_table.h" ++ ++/* command between backend and frontend */ ++#define VSCSIIF_ACT_SCSI_CDB 1 /* SCSI CDB command */ ++#define VSCSIIF_ACT_SCSI_ABORT 2 /* SCSI Device(Lun) Abort*/ ++#define VSCSIIF_ACT_SCSI_RESET 3 /* SCSI Device(Lun) Reset*/ ++ ++ ++#define VSCSIIF_BACK_MAX_PENDING_REQS 128 ++ ++/* ++ * Maximum scatter/gather segments per request. ++ * ++ * Considering balance between allocating al least 16 "vscsiif_request" ++ * structures on one page (4096bytes) and number of scatter gather ++ * needed, we decided to use 26 as a magic number. ++ */ ++#define VSCSIIF_SG_TABLESIZE 26 ++ ++/* ++ * base on linux kernel 2.6.18 ++ */ ++#define VSCSIIF_MAX_COMMAND_SIZE 16 ++#define VSCSIIF_SENSE_BUFFERSIZE 96 ++ ++ ++struct vscsiif_request { ++ uint16_t rqid; /* private guest value, echoed in resp */ ++ uint8_t act; /* command between backend and frontend */ ++ uint8_t cmd_len; ++ ++ uint8_t cmnd[VSCSIIF_MAX_COMMAND_SIZE]; ++ uint16_t timeout_per_command; /* The command is issued by twice ++ the value in Backend. */ ++ uint16_t channel, id, lun; ++ uint16_t padding; ++ uint8_t sc_data_direction; /* for DMA_TO_DEVICE(1) ++ DMA_FROM_DEVICE(2) ++ DMA_NONE(3) requests */ ++ uint8_t nr_segments; /* Number of pieces of scatter-gather */ ++ ++ struct scsiif_request_segment { ++ grant_ref_t gref; ++ uint16_t offset; ++ uint16_t length; ++ } seg[VSCSIIF_SG_TABLESIZE]; ++ uint32_t reserved[3]; ++}; ++typedef struct vscsiif_request vscsiif_request_t; ++ ++struct vscsiif_response { ++ uint16_t rqid; ++ uint8_t padding; ++ uint8_t sense_len; ++ uint8_t sense_buffer[VSCSIIF_SENSE_BUFFERSIZE]; ++ int32_t rslt; ++ uint32_t residual_len; /* request bufflen - ++ return the value from physical device */ ++ uint32_t reserved[36]; ++}; ++typedef struct vscsiif_response vscsiif_response_t; ++ ++DEFINE_RING_TYPES(vscsiif, struct vscsiif_request, struct vscsiif_response); ++ ++ ++#endif /*__XEN__PUBLIC_IO_SCSI_H__*/ ++/* ++ * Local variables: ++ * mode: C ++ * c-set-style: "BSD" ++ * c-basic-offset: 4 ++ * tab-width: 4 ++ * indent-tabs-mode: nil ++ * End: ++ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/include/xen/interface/kexec.h 2008-11-25 12:22:34.000000000 +0100 +@@ -0,0 +1,168 @@ ++/****************************************************************************** ++ * kexec.h - Public portion ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to ++ * deal in the Software without restriction, including without limitation the ++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ++ * DEALINGS IN THE SOFTWARE. ++ * ++ * Xen port written by: ++ * - Simon 'Horms' Horman ++ * - Magnus Damm ++ */ ++ ++#ifndef _XEN_PUBLIC_KEXEC_H ++#define _XEN_PUBLIC_KEXEC_H ++ ++ ++/* This file describes the Kexec / Kdump hypercall interface for Xen. ++ * ++ * Kexec under vanilla Linux allows a user to reboot the physical machine ++ * into a new user-specified kernel. The Xen port extends this idea ++ * to allow rebooting of the machine from dom0. When kexec for dom0 ++ * is used to reboot, both the hypervisor and the domains get replaced ++ * with some other kernel. It is possible to kexec between vanilla ++ * Linux and Xen and back again. Xen to Xen works well too. ++ * ++ * The hypercall interface for kexec can be divided into three main ++ * types of hypercall operations: ++ * ++ * 1) Range information: ++ * This is used by the dom0 kernel to ask the hypervisor about various ++ * address information. This information is needed to allow kexec-tools ++ * to fill in the ELF headers for /proc/vmcore properly. ++ * ++ * 2) Load and unload of images: ++ * There are no big surprises here, the kexec binary from kexec-tools ++ * runs in userspace in dom0. The tool loads/unloads data into the ++ * dom0 kernel such as new kernel, initramfs and hypervisor. When ++ * loaded the dom0 kernel performs a load hypercall operation, and ++ * before releasing all page references the dom0 kernel calls unload. ++ * ++ * 3) Kexec operation: ++ * This is used to start a previously loaded kernel. ++ */ ++ ++#include "xen.h" ++ ++#if defined(__i386__) || defined(__x86_64__) ++#define KEXEC_XEN_NO_PAGES 17 ++#endif ++ ++/* ++ * Prototype for this hypercall is: ++ * int kexec_op(int cmd, void *args) ++ * @cmd == KEXEC_CMD_... ++ * KEXEC operation to perform ++ * @args == Operation-specific extra arguments (NULL if none). ++ */ ++ ++/* ++ * Kexec supports two types of operation: ++ * - kexec into a regular kernel, very similar to a standard reboot ++ * - KEXEC_TYPE_DEFAULT is used to specify this type ++ * - kexec into a special "crash kernel", aka kexec-on-panic ++ * - KEXEC_TYPE_CRASH is used to specify this type ++ * - parts of our system may be broken at kexec-on-panic time ++ * - the code should be kept as simple and self-contained as possible ++ */ ++ ++#define KEXEC_TYPE_DEFAULT 0 ++#define KEXEC_TYPE_CRASH 1 ++ ++ ++/* The kexec implementation for Xen allows the user to load two ++ * types of kernels, KEXEC_TYPE_DEFAULT and KEXEC_TYPE_CRASH. ++ * All data needed for a kexec reboot is kept in one xen_kexec_image_t ++ * per "instance". The data mainly consists of machine address lists to pages ++ * together with destination addresses. The data in xen_kexec_image_t ++ * is passed to the "code page" which is one page of code that performs ++ * the final relocations before jumping to the new kernel. ++ */ ++ ++typedef struct xen_kexec_image { ++#if defined(__i386__) || defined(__x86_64__) ++ unsigned long page_list[KEXEC_XEN_NO_PAGES]; ++#endif ++#if defined(__ia64__) ++ unsigned long reboot_code_buffer; ++#endif ++ unsigned long indirection_page; ++ unsigned long start_address; ++} xen_kexec_image_t; ++ ++/* ++ * Perform kexec having previously loaded a kexec or kdump kernel ++ * as appropriate. ++ * type == KEXEC_TYPE_DEFAULT or KEXEC_TYPE_CRASH [in] ++ */ ++#define KEXEC_CMD_kexec 0 ++typedef struct xen_kexec_exec { ++ int type; ++} xen_kexec_exec_t; ++ ++/* ++ * Load/Unload kernel image for kexec or kdump. ++ * type == KEXEC_TYPE_DEFAULT or KEXEC_TYPE_CRASH [in] ++ * image == relocation information for kexec (ignored for unload) [in] ++ */ ++#define KEXEC_CMD_kexec_load 1 ++#define KEXEC_CMD_kexec_unload 2 ++typedef struct xen_kexec_load { ++ int type; ++ xen_kexec_image_t image; ++} xen_kexec_load_t; ++ ++#define KEXEC_RANGE_MA_CRASH 0 /* machine address and size of crash area */ ++#define KEXEC_RANGE_MA_XEN 1 /* machine address and size of Xen itself */ ++#define KEXEC_RANGE_MA_CPU 2 /* machine address and size of a CPU note */ ++#define KEXEC_RANGE_MA_XENHEAP 3 /* machine address and size of xenheap ++ * Note that although this is adjacent ++ * to Xen it exists in a separate EFI ++ * region on ia64, and thus needs to be ++ * inserted into iomem_machine separately */ ++#define KEXEC_RANGE_MA_BOOT_PARAM 4 /* machine address and size of ++ * the ia64_boot_param */ ++#define KEXEC_RANGE_MA_EFI_MEMMAP 5 /* machine address and size of ++ * of the EFI Memory Map */ ++#define KEXEC_RANGE_MA_VMCOREINFO 6 /* machine address and size of vmcoreinfo */ ++ ++/* ++ * Find the address and size of certain memory areas ++ * range == KEXEC_RANGE_... [in] ++ * nr == physical CPU number (starting from 0) if KEXEC_RANGE_MA_CPU [in] ++ * size == number of bytes reserved in window [out] ++ * start == address of the first byte in the window [out] ++ */ ++#define KEXEC_CMD_kexec_get_range 3 ++typedef struct xen_kexec_range { ++ int range; ++ int nr; ++ unsigned long size; ++ unsigned long start; ++} xen_kexec_range_t; ++ ++#endif /* _XEN_PUBLIC_KEXEC_H */ ++ ++/* ++ * Local variables: ++ * mode: C ++ * c-set-style: "BSD" ++ * c-basic-offset: 4 ++ * tab-width: 4 ++ * indent-tabs-mode: nil ++ * End: ++ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/include/xen/interface/mem_event.h 2010-01-04 11:56:34.000000000 +0100 +@@ -0,0 +1,69 @@ ++/****************************************************************************** ++ * mem_event.h ++ * ++ * Memory event common structures. ++ * ++ * Copyright (c) 2009 by Citrix Systems, Inc. (Patrick Colp) ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++#ifndef _XEN_PUBLIC_MEM_EVENT_H ++#define _XEN_PUBLIC_MEM_EVENT_H ++ ++ ++#include "xen.h" ++#include "io/ring.h" ++ ++ ++/* Memory event notification modes */ ++#define MEM_EVENT_MODE_ASYNC 0 ++#define MEM_EVENT_MODE_SYNC (1 << 0) ++#define MEM_EVENT_MODE_SYNC_ALL (1 << 1) ++ ++/* Memory event flags */ ++#define MEM_EVENT_FLAG_VCPU_PAUSED (1 << 0) ++#define MEM_EVENT_FLAG_DOM_PAUSED (1 << 1) ++#define MEM_EVENT_FLAG_OUT_OF_MEM (1 << 2) ++ ++ ++typedef struct mem_event_shared_page { ++ int port; ++} mem_event_shared_page_t; ++ ++typedef struct mem_event_st { ++ unsigned long gfn; ++ unsigned long offset; ++ unsigned long p2mt; ++ int vcpu_id; ++ uint64_t flags; ++} mem_event_request_t, mem_event_response_t; ++ ++ ++DEFINE_RING_TYPES(mem_event, mem_event_request_t, mem_event_response_t); ++ ++ ++#endif ++ ++ ++/* ++ * Local variables: ++ * mode: C ++ * c-set-style: "BSD" ++ * c-basic-offset: 4 ++ * tab-width: 4 ++ * indent-tabs-mode: nil ++ * End: ++ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/include/xen/interface/nmi.h 2009-06-23 09:28:21.000000000 +0200 +@@ -0,0 +1,80 @@ ++/****************************************************************************** ++ * nmi.h ++ * ++ * NMI callback registration and reason codes. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to ++ * deal in the Software without restriction, including without limitation the ++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ++ * DEALINGS IN THE SOFTWARE. ++ * ++ * Copyright (c) 2005, Keir Fraser ++ */ ++ ++#ifndef __XEN_PUBLIC_NMI_H__ ++#define __XEN_PUBLIC_NMI_H__ ++ ++#include "xen.h" ++ ++/* ++ * NMI reason codes: ++ * Currently these are x86-specific, stored in arch_shared_info.nmi_reason. ++ */ ++ /* I/O-check error reported via ISA port 0x61, bit 6. */ ++#define _XEN_NMIREASON_io_error 0 ++#define XEN_NMIREASON_io_error (1UL << _XEN_NMIREASON_io_error) ++ /* Parity error reported via ISA port 0x61, bit 7. */ ++#define _XEN_NMIREASON_parity_error 1 ++#define XEN_NMIREASON_parity_error (1UL << _XEN_NMIREASON_parity_error) ++ /* Unknown hardware-generated NMI. */ ++#define _XEN_NMIREASON_unknown 2 ++#define XEN_NMIREASON_unknown (1UL << _XEN_NMIREASON_unknown) ++ ++/* ++ * long nmi_op(unsigned int cmd, void *arg) ++ * NB. All ops return zero on success, else a negative error code. ++ */ ++ ++/* ++ * Register NMI callback for this (calling) VCPU. Currently this only makes ++ * sense for domain 0, vcpu 0. All other callers will be returned EINVAL. ++ * arg == pointer to xennmi_callback structure. ++ */ ++#define XENNMI_register_callback 0 ++struct xennmi_callback { ++ unsigned long handler_address; ++ unsigned long pad; ++}; ++typedef struct xennmi_callback xennmi_callback_t; ++DEFINE_XEN_GUEST_HANDLE(xennmi_callback_t); ++ ++/* ++ * Deregister NMI callback for this (calling) VCPU. ++ * arg == NULL. ++ */ ++#define XENNMI_unregister_callback 1 ++ ++#endif /* __XEN_PUBLIC_NMI_H__ */ ++ ++/* ++ * Local variables: ++ * mode: C ++ * c-set-style: "BSD" ++ * c-basic-offset: 4 ++ * tab-width: 4 ++ * indent-tabs-mode: nil ++ * End: ++ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/include/xen/interface/platform.h 2010-01-04 11:56:34.000000000 +0100 +@@ -0,0 +1,393 @@ ++/****************************************************************************** ++ * platform.h ++ * ++ * Hardware platform operations. Intended for use by domain-0 kernel. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to ++ * deal in the Software without restriction, including without limitation the ++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ++ * DEALINGS IN THE SOFTWARE. ++ * ++ * Copyright (c) 2002-2006, K Fraser ++ */ ++ ++#ifndef __XEN_PUBLIC_PLATFORM_H__ ++#define __XEN_PUBLIC_PLATFORM_H__ ++ ++#include "xen.h" ++ ++#define XENPF_INTERFACE_VERSION 0x03000001 ++ ++/* ++ * Set clock such that it would read after 00:00:00 UTC, ++ * 1 January, 1970 if the current system time was . ++ */ ++#define XENPF_settime 17 ++struct xenpf_settime { ++ /* IN variables. */ ++ uint32_t secs; ++ uint32_t nsecs; ++ uint64_t system_time; ++}; ++typedef struct xenpf_settime xenpf_settime_t; ++DEFINE_XEN_GUEST_HANDLE(xenpf_settime_t); ++ ++/* ++ * Request memory range (@mfn, @mfn+@nr_mfns-1) to have type @type. ++ * On x86, @type is an architecture-defined MTRR memory type. ++ * On success, returns the MTRR that was used (@reg) and a handle that can ++ * be passed to XENPF_DEL_MEMTYPE to accurately tear down the new setting. ++ * (x86-specific). ++ */ ++#define XENPF_add_memtype 31 ++struct xenpf_add_memtype { ++ /* IN variables. */ ++ xen_pfn_t mfn; ++ uint64_t nr_mfns; ++ uint32_t type; ++ /* OUT variables. */ ++ uint32_t handle; ++ uint32_t reg; ++}; ++typedef struct xenpf_add_memtype xenpf_add_memtype_t; ++DEFINE_XEN_GUEST_HANDLE(xenpf_add_memtype_t); ++ ++/* ++ * Tear down an existing memory-range type. If @handle is remembered then it ++ * should be passed in to accurately tear down the correct setting (in case ++ * of overlapping memory regions with differing types). If it is not known ++ * then @handle should be set to zero. In all cases @reg must be set. ++ * (x86-specific). ++ */ ++#define XENPF_del_memtype 32 ++struct xenpf_del_memtype { ++ /* IN variables. */ ++ uint32_t handle; ++ uint32_t reg; ++}; ++typedef struct xenpf_del_memtype xenpf_del_memtype_t; ++DEFINE_XEN_GUEST_HANDLE(xenpf_del_memtype_t); ++ ++/* Read current type of an MTRR (x86-specific). */ ++#define XENPF_read_memtype 33 ++struct xenpf_read_memtype { ++ /* IN variables. */ ++ uint32_t reg; ++ /* OUT variables. */ ++ xen_pfn_t mfn; ++ uint64_t nr_mfns; ++ uint32_t type; ++}; ++typedef struct xenpf_read_memtype xenpf_read_memtype_t; ++DEFINE_XEN_GUEST_HANDLE(xenpf_read_memtype_t); ++ ++#define XENPF_microcode_update 35 ++struct xenpf_microcode_update { ++ /* IN variables. */ ++ XEN_GUEST_HANDLE(const_void) data;/* Pointer to microcode data */ ++ uint32_t length; /* Length of microcode data. */ ++}; ++typedef struct xenpf_microcode_update xenpf_microcode_update_t; ++DEFINE_XEN_GUEST_HANDLE(xenpf_microcode_update_t); ++ ++#define XENPF_platform_quirk 39 ++#define QUIRK_NOIRQBALANCING 1 /* Do not restrict IO-APIC RTE targets */ ++#define QUIRK_IOAPIC_BAD_REGSEL 2 /* IO-APIC REGSEL forgets its value */ ++#define QUIRK_IOAPIC_GOOD_REGSEL 3 /* IO-APIC REGSEL behaves properly */ ++struct xenpf_platform_quirk { ++ /* IN variables. */ ++ uint32_t quirk_id; ++}; ++typedef struct xenpf_platform_quirk xenpf_platform_quirk_t; ++DEFINE_XEN_GUEST_HANDLE(xenpf_platform_quirk_t); ++ ++#define XENPF_firmware_info 50 ++#define XEN_FW_DISK_INFO 1 /* from int 13 AH=08/41/48 */ ++#define XEN_FW_DISK_MBR_SIGNATURE 2 /* from MBR offset 0x1b8 */ ++#define XEN_FW_VBEDDC_INFO 3 /* from int 10 AX=4f15 */ ++struct xenpf_firmware_info { ++ /* IN variables. */ ++ uint32_t type; ++ uint32_t index; ++ /* OUT variables. */ ++ union { ++ struct { ++ /* Int13, Fn48: Check Extensions Present. */ ++ uint8_t device; /* %dl: bios device number */ ++ uint8_t version; /* %ah: major version */ ++ uint16_t interface_support; /* %cx: support bitmap */ ++ /* Int13, Fn08: Legacy Get Device Parameters. */ ++ uint16_t legacy_max_cylinder; /* %cl[7:6]:%ch: max cyl # */ ++ uint8_t legacy_max_head; /* %dh: max head # */ ++ uint8_t legacy_sectors_per_track; /* %cl[5:0]: max sector # */ ++ /* Int13, Fn41: Get Device Parameters (as filled into %ds:%esi). */ ++ /* NB. First uint16_t of buffer must be set to buffer size. */ ++ XEN_GUEST_HANDLE(void) edd_params; ++ } disk_info; /* XEN_FW_DISK_INFO */ ++ struct { ++ uint8_t device; /* bios device number */ ++ uint32_t mbr_signature; /* offset 0x1b8 in mbr */ ++ } disk_mbr_signature; /* XEN_FW_DISK_MBR_SIGNATURE */ ++ struct { ++ /* Int10, AX=4F15: Get EDID info. */ ++ uint8_t capabilities; ++ uint8_t edid_transfer_time; ++ /* must refer to 128-byte buffer */ ++ XEN_GUEST_HANDLE(uint8) edid; ++ } vbeddc_info; /* XEN_FW_VBEDDC_INFO */ ++ } u; ++}; ++typedef struct xenpf_firmware_info xenpf_firmware_info_t; ++DEFINE_XEN_GUEST_HANDLE(xenpf_firmware_info_t); ++ ++#define XENPF_enter_acpi_sleep 51 ++struct xenpf_enter_acpi_sleep { ++ /* IN variables */ ++ uint16_t pm1a_cnt_val; /* PM1a control value. */ ++ uint16_t pm1b_cnt_val; /* PM1b control value. */ ++ uint32_t sleep_state; /* Which state to enter (Sn). */ ++ uint32_t flags; /* Must be zero. */ ++}; ++typedef struct xenpf_enter_acpi_sleep xenpf_enter_acpi_sleep_t; ++DEFINE_XEN_GUEST_HANDLE(xenpf_enter_acpi_sleep_t); ++ ++#define XENPF_change_freq 52 ++struct xenpf_change_freq { ++ /* IN variables */ ++ uint32_t flags; /* Must be zero. */ ++ uint32_t cpu; /* Physical cpu. */ ++ uint64_t freq; /* New frequency (Hz). */ ++}; ++typedef struct xenpf_change_freq xenpf_change_freq_t; ++DEFINE_XEN_GUEST_HANDLE(xenpf_change_freq_t); ++ ++/* ++ * Get idle times (nanoseconds since boot) for physical CPUs specified in the ++ * @cpumap_bitmap with range [0..@cpumap_nr_cpus-1]. The @idletime array is ++ * indexed by CPU number; only entries with the corresponding @cpumap_bitmap ++ * bit set are written to. On return, @cpumap_bitmap is modified so that any ++ * non-existent CPUs are cleared. Such CPUs have their @idletime array entry ++ * cleared. ++ */ ++#define XENPF_getidletime 53 ++struct xenpf_getidletime { ++ /* IN/OUT variables */ ++ /* IN: CPUs to interrogate; OUT: subset of IN which are present */ ++ XEN_GUEST_HANDLE(uint8) cpumap_bitmap; ++ /* IN variables */ ++ /* Size of cpumap bitmap. */ ++ uint32_t cpumap_nr_cpus; ++ /* Must be indexable for every cpu in cpumap_bitmap. */ ++ XEN_GUEST_HANDLE(uint64) idletime; ++ /* OUT variables */ ++ /* System time when the idletime snapshots were taken. */ ++ uint64_t now; ++}; ++typedef struct xenpf_getidletime xenpf_getidletime_t; ++DEFINE_XEN_GUEST_HANDLE(xenpf_getidletime_t); ++ ++#define XENPF_set_processor_pminfo 54 ++ ++/* ability bits */ ++#define XEN_PROCESSOR_PM_CX 1 ++#define XEN_PROCESSOR_PM_PX 2 ++#define XEN_PROCESSOR_PM_TX 4 ++ ++/* cmd type */ ++#define XEN_PM_CX 0 ++#define XEN_PM_PX 1 ++#define XEN_PM_TX 2 ++ ++/* Px sub info type */ ++#define XEN_PX_PCT 1 ++#define XEN_PX_PSS 2 ++#define XEN_PX_PPC 4 ++#define XEN_PX_PSD 8 ++ ++struct xen_power_register { ++ uint32_t space_id; ++ uint32_t bit_width; ++ uint32_t bit_offset; ++ uint32_t access_size; ++ uint64_t address; ++}; ++ ++struct xen_processor_csd { ++ uint32_t domain; /* domain number of one dependent group */ ++ uint32_t coord_type; /* coordination type */ ++ uint32_t num; /* number of processors in same domain */ ++}; ++typedef struct xen_processor_csd xen_processor_csd_t; ++DEFINE_XEN_GUEST_HANDLE(xen_processor_csd_t); ++ ++struct xen_processor_cx { ++ struct xen_power_register reg; /* GAS for Cx trigger register */ ++ uint8_t type; /* cstate value, c0: 0, c1: 1, ... */ ++ uint32_t latency; /* worst latency (ms) to enter/exit this cstate */ ++ uint32_t power; /* average power consumption(mW) */ ++ uint32_t dpcnt; /* number of dependency entries */ ++ XEN_GUEST_HANDLE(xen_processor_csd_t) dp; /* NULL if no dependency */ ++}; ++typedef struct xen_processor_cx xen_processor_cx_t; ++DEFINE_XEN_GUEST_HANDLE(xen_processor_cx_t); ++ ++struct xen_processor_flags { ++ uint32_t bm_control:1; ++ uint32_t bm_check:1; ++ uint32_t has_cst:1; ++ uint32_t power_setup_done:1; ++ uint32_t bm_rld_set:1; ++}; ++ ++struct xen_processor_power { ++ uint32_t count; /* number of C state entries in array below */ ++ struct xen_processor_flags flags; /* global flags of this processor */ ++ XEN_GUEST_HANDLE(xen_processor_cx_t) states; /* supported c states */ ++}; ++ ++struct xen_pct_register { ++ uint8_t descriptor; ++ uint16_t length; ++ uint8_t space_id; ++ uint8_t bit_width; ++ uint8_t bit_offset; ++ uint8_t reserved; ++ uint64_t address; ++}; ++ ++struct xen_processor_px { ++ uint64_t core_frequency; /* megahertz */ ++ uint64_t power; /* milliWatts */ ++ uint64_t transition_latency; /* microseconds */ ++ uint64_t bus_master_latency; /* microseconds */ ++ uint64_t control; /* control value */ ++ uint64_t status; /* success indicator */ ++}; ++typedef struct xen_processor_px xen_processor_px_t; ++DEFINE_XEN_GUEST_HANDLE(xen_processor_px_t); ++ ++struct xen_psd_package { ++ uint64_t num_entries; ++ uint64_t revision; ++ uint64_t domain; ++ uint64_t coord_type; ++ uint64_t num_processors; ++}; ++ ++struct xen_processor_performance { ++ uint32_t flags; /* flag for Px sub info type */ ++ uint32_t platform_limit; /* Platform limitation on freq usage */ ++ struct xen_pct_register control_register; ++ struct xen_pct_register status_register; ++ uint32_t state_count; /* total available performance states */ ++ XEN_GUEST_HANDLE(xen_processor_px_t) states; ++ struct xen_psd_package domain_info; ++ uint32_t shared_type; /* coordination type of this processor */ ++}; ++typedef struct xen_processor_performance xen_processor_performance_t; ++DEFINE_XEN_GUEST_HANDLE(xen_processor_performance_t); ++ ++struct xenpf_set_processor_pminfo { ++ /* IN variables */ ++ uint32_t id; /* ACPI CPU ID */ ++ uint32_t type; /* {XEN_PM_CX, XEN_PM_PX} */ ++ union { ++ struct xen_processor_power power;/* Cx: _CST/_CSD */ ++ struct xen_processor_performance perf; /* Px: _PPC/_PCT/_PSS/_PSD */ ++ } u; ++}; ++typedef struct xenpf_set_processor_pminfo xenpf_set_processor_pminfo_t; ++DEFINE_XEN_GUEST_HANDLE(xenpf_set_processor_pminfo_t); ++ ++#define XENPF_get_cpuinfo 55 ++struct xenpf_pcpuinfo { ++ /* IN */ ++ uint32_t xen_cpuid; ++ /* OUT */ ++ /* The maxium cpu_id that is present */ ++ uint32_t max_present; ++#define XEN_PCPU_FLAGS_ONLINE 1 ++ /* Correponding xen_cpuid is not present*/ ++#define XEN_PCPU_FLAGS_INVALID 2 ++ uint32_t flags; ++ uint32_t apic_id; ++ uint32_t acpi_id; ++}; ++typedef struct xenpf_pcpuinfo xenpf_pcpuinfo_t; ++DEFINE_XEN_GUEST_HANDLE(xenpf_pcpuinfo_t); ++ ++#define XENPF_cpu_online 56 ++#define XENPF_cpu_offline 57 ++struct xenpf_cpu_ol ++{ ++ uint32_t cpuid; ++}; ++typedef struct xenpf_cpu_ol xenpf_cpu_ol_t; ++DEFINE_XEN_GUEST_HANDLE(xenpf_cpu_ol_t); ++ ++#define XENPF_cpu_hotadd 58 ++struct xenpf_cpu_hotadd ++{ ++ uint32_t apic_id; ++ uint32_t acpi_id; ++ uint32_t pxm; ++}; ++ ++#define XENPF_mem_hotadd 59 ++struct xenpf_mem_hotadd ++{ ++ uint64_t spfn; ++ uint64_t epfn; ++ uint32_t pxm; ++ uint32_t flags; ++}; ++ ++struct xen_platform_op { ++ uint32_t cmd; ++ uint32_t interface_version; /* XENPF_INTERFACE_VERSION */ ++ union { ++ struct xenpf_settime settime; ++ struct xenpf_add_memtype add_memtype; ++ struct xenpf_del_memtype del_memtype; ++ struct xenpf_read_memtype read_memtype; ++ struct xenpf_microcode_update microcode; ++ struct xenpf_platform_quirk platform_quirk; ++ struct xenpf_firmware_info firmware_info; ++ struct xenpf_enter_acpi_sleep enter_acpi_sleep; ++ struct xenpf_change_freq change_freq; ++ struct xenpf_getidletime getidletime; ++ struct xenpf_set_processor_pminfo set_pminfo; ++ struct xenpf_pcpuinfo pcpu_info; ++ struct xenpf_cpu_ol cpu_ol; ++ struct xenpf_cpu_hotadd cpu_add; ++ struct xenpf_mem_hotadd mem_add; ++ uint8_t pad[128]; ++ } u; ++}; ++typedef struct xen_platform_op xen_platform_op_t; ++DEFINE_XEN_GUEST_HANDLE(xen_platform_op_t); ++ ++#endif /* __XEN_PUBLIC_PLATFORM_H__ */ ++ ++/* ++ * Local variables: ++ * mode: C ++ * c-set-style: "BSD" ++ * c-basic-offset: 4 ++ * tab-width: 4 ++ * indent-tabs-mode: nil ++ * End: ++ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/include/xen/interface/sysctl.h 2010-01-18 15:23:12.000000000 +0100 +@@ -0,0 +1,523 @@ ++/****************************************************************************** ++ * sysctl.h ++ * ++ * System management operations. For use by node control stack. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to ++ * deal in the Software without restriction, including without limitation the ++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ++ * DEALINGS IN THE SOFTWARE. ++ * ++ * Copyright (c) 2002-2006, K Fraser ++ */ ++ ++#ifndef __XEN_PUBLIC_SYSCTL_H__ ++#define __XEN_PUBLIC_SYSCTL_H__ ++ ++#if !defined(__XEN__) && !defined(__XEN_TOOLS__) ++#error "sysctl operations are intended for use by node control tools only" ++#endif ++ ++#include "xen.h" ++#include "domctl.h" ++ ++#define XEN_SYSCTL_INTERFACE_VERSION 0x00000007 ++ ++/* ++ * Read console content from Xen buffer ring. ++ */ ++#define XEN_SYSCTL_readconsole 1 ++struct xen_sysctl_readconsole { ++ /* IN: Non-zero -> clear after reading. */ ++ uint8_t clear; ++ /* IN: Non-zero -> start index specified by @index field. */ ++ uint8_t incremental; ++ uint8_t pad0, pad1; ++ /* ++ * IN: Start index for consuming from ring buffer (if @incremental); ++ * OUT: End index after consuming from ring buffer. ++ */ ++ uint32_t index; ++ /* IN: Virtual address to write console data. */ ++ XEN_GUEST_HANDLE_64(char) buffer; ++ /* IN: Size of buffer; OUT: Bytes written to buffer. */ ++ uint32_t count; ++}; ++typedef struct xen_sysctl_readconsole xen_sysctl_readconsole_t; ++DEFINE_XEN_GUEST_HANDLE(xen_sysctl_readconsole_t); ++ ++/* Get trace buffers machine base address */ ++#define XEN_SYSCTL_tbuf_op 2 ++struct xen_sysctl_tbuf_op { ++ /* IN variables */ ++#define XEN_SYSCTL_TBUFOP_get_info 0 ++#define XEN_SYSCTL_TBUFOP_set_cpu_mask 1 ++#define XEN_SYSCTL_TBUFOP_set_evt_mask 2 ++#define XEN_SYSCTL_TBUFOP_set_size 3 ++#define XEN_SYSCTL_TBUFOP_enable 4 ++#define XEN_SYSCTL_TBUFOP_disable 5 ++ uint32_t cmd; ++ /* IN/OUT variables */ ++ struct xenctl_cpumap cpu_mask; ++ uint32_t evt_mask; ++ /* OUT variables */ ++ uint64_aligned_t buffer_mfn; ++ uint32_t size; ++}; ++typedef struct xen_sysctl_tbuf_op xen_sysctl_tbuf_op_t; ++DEFINE_XEN_GUEST_HANDLE(xen_sysctl_tbuf_op_t); ++ ++/* ++ * Get physical information about the host machine ++ */ ++#define XEN_SYSCTL_physinfo 3 ++ /* (x86) The platform supports HVM guests. */ ++#define _XEN_SYSCTL_PHYSCAP_hvm 0 ++#define XEN_SYSCTL_PHYSCAP_hvm (1u<<_XEN_SYSCTL_PHYSCAP_hvm) ++ /* (x86) The platform supports HVM-guest direct access to I/O devices. */ ++#define _XEN_SYSCTL_PHYSCAP_hvm_directio 1 ++#define XEN_SYSCTL_PHYSCAP_hvm_directio (1u<<_XEN_SYSCTL_PHYSCAP_hvm_directio) ++struct xen_sysctl_physinfo { ++ uint32_t threads_per_core; ++ uint32_t cores_per_socket; ++ uint32_t nr_cpus; ++ uint32_t max_node_id; ++ uint32_t cpu_khz; ++ uint64_aligned_t total_pages; ++ uint64_aligned_t free_pages; ++ uint64_aligned_t scrub_pages; ++ uint32_t hw_cap[8]; ++ ++ /* ++ * IN: maximum addressable entry in the caller-provided cpu_to_node array. ++ * OUT: largest cpu identifier in the system. ++ * If OUT is greater than IN then the cpu_to_node array is truncated! ++ */ ++ uint32_t max_cpu_id; ++ /* ++ * If not NULL, this array is filled with node identifier for each cpu. ++ * If a cpu has no node information (e.g., cpu not present) then the ++ * sentinel value ~0u is written. ++ * The size of this array is specified by the caller in @max_cpu_id. ++ * If the actual @max_cpu_id is smaller than the array then the trailing ++ * elements of the array will not be written by the sysctl. ++ */ ++ XEN_GUEST_HANDLE_64(uint32) cpu_to_node; ++ ++ /* XEN_SYSCTL_PHYSCAP_??? */ ++ uint32_t capabilities; ++}; ++typedef struct xen_sysctl_physinfo xen_sysctl_physinfo_t; ++DEFINE_XEN_GUEST_HANDLE(xen_sysctl_physinfo_t); ++ ++/* ++ * Get the ID of the current scheduler. ++ */ ++#define XEN_SYSCTL_sched_id 4 ++struct xen_sysctl_sched_id { ++ /* OUT variable */ ++ uint32_t sched_id; ++}; ++typedef struct xen_sysctl_sched_id xen_sysctl_sched_id_t; ++DEFINE_XEN_GUEST_HANDLE(xen_sysctl_sched_id_t); ++ ++/* Interface for controlling Xen software performance counters. */ ++#define XEN_SYSCTL_perfc_op 5 ++/* Sub-operations: */ ++#define XEN_SYSCTL_PERFCOP_reset 1 /* Reset all counters to zero. */ ++#define XEN_SYSCTL_PERFCOP_query 2 /* Get perfctr information. */ ++struct xen_sysctl_perfc_desc { ++ char name[80]; /* name of perf counter */ ++ uint32_t nr_vals; /* number of values for this counter */ ++}; ++typedef struct xen_sysctl_perfc_desc xen_sysctl_perfc_desc_t; ++DEFINE_XEN_GUEST_HANDLE(xen_sysctl_perfc_desc_t); ++typedef uint32_t xen_sysctl_perfc_val_t; ++DEFINE_XEN_GUEST_HANDLE(xen_sysctl_perfc_val_t); ++ ++struct xen_sysctl_perfc_op { ++ /* IN variables. */ ++ uint32_t cmd; /* XEN_SYSCTL_PERFCOP_??? */ ++ /* OUT variables. */ ++ uint32_t nr_counters; /* number of counters description */ ++ uint32_t nr_vals; /* number of values */ ++ /* counter information (or NULL) */ ++ XEN_GUEST_HANDLE_64(xen_sysctl_perfc_desc_t) desc; ++ /* counter values (or NULL) */ ++ XEN_GUEST_HANDLE_64(xen_sysctl_perfc_val_t) val; ++}; ++typedef struct xen_sysctl_perfc_op xen_sysctl_perfc_op_t; ++DEFINE_XEN_GUEST_HANDLE(xen_sysctl_perfc_op_t); ++ ++#define XEN_SYSCTL_getdomaininfolist 6 ++struct xen_sysctl_getdomaininfolist { ++ /* IN variables. */ ++ domid_t first_domain; ++ uint32_t max_domains; ++ XEN_GUEST_HANDLE_64(xen_domctl_getdomaininfo_t) buffer; ++ /* OUT variables. */ ++ uint32_t num_domains; ++}; ++typedef struct xen_sysctl_getdomaininfolist xen_sysctl_getdomaininfolist_t; ++DEFINE_XEN_GUEST_HANDLE(xen_sysctl_getdomaininfolist_t); ++ ++/* Inject debug keys into Xen. */ ++#define XEN_SYSCTL_debug_keys 7 ++struct xen_sysctl_debug_keys { ++ /* IN variables. */ ++ XEN_GUEST_HANDLE_64(char) keys; ++ uint32_t nr_keys; ++}; ++typedef struct xen_sysctl_debug_keys xen_sysctl_debug_keys_t; ++DEFINE_XEN_GUEST_HANDLE(xen_sysctl_debug_keys_t); ++ ++/* Get physical CPU information. */ ++#define XEN_SYSCTL_getcpuinfo 8 ++struct xen_sysctl_cpuinfo { ++ uint64_aligned_t idletime; ++}; ++typedef struct xen_sysctl_cpuinfo xen_sysctl_cpuinfo_t; ++DEFINE_XEN_GUEST_HANDLE(xen_sysctl_cpuinfo_t); ++struct xen_sysctl_getcpuinfo { ++ /* IN variables. */ ++ uint32_t max_cpus; ++ XEN_GUEST_HANDLE_64(xen_sysctl_cpuinfo_t) info; ++ /* OUT variables. */ ++ uint32_t nr_cpus; ++}; ++typedef struct xen_sysctl_getcpuinfo xen_sysctl_getcpuinfo_t; ++DEFINE_XEN_GUEST_HANDLE(xen_sysctl_getcpuinfo_t); ++ ++#define XEN_SYSCTL_availheap 9 ++struct xen_sysctl_availheap { ++ /* IN variables. */ ++ uint32_t min_bitwidth; /* Smallest address width (zero if don't care). */ ++ uint32_t max_bitwidth; /* Largest address width (zero if don't care). */ ++ int32_t node; /* NUMA node of interest (-1 for all nodes). */ ++ /* OUT variables. */ ++ uint64_aligned_t avail_bytes;/* Bytes available in the specified region. */ ++}; ++typedef struct xen_sysctl_availheap xen_sysctl_availheap_t; ++DEFINE_XEN_GUEST_HANDLE(xen_sysctl_availheap_t); ++ ++#define XEN_SYSCTL_get_pmstat 10 ++struct pm_px_val { ++ uint64_aligned_t freq; /* Px core frequency */ ++ uint64_aligned_t residency; /* Px residency time */ ++ uint64_aligned_t count; /* Px transition count */ ++}; ++typedef struct pm_px_val pm_px_val_t; ++DEFINE_XEN_GUEST_HANDLE(pm_px_val_t); ++ ++struct pm_px_stat { ++ uint8_t total; /* total Px states */ ++ uint8_t usable; /* usable Px states */ ++ uint8_t last; /* last Px state */ ++ uint8_t cur; /* current Px state */ ++ XEN_GUEST_HANDLE_64(uint64) trans_pt; /* Px transition table */ ++ XEN_GUEST_HANDLE_64(pm_px_val_t) pt; ++}; ++typedef struct pm_px_stat pm_px_stat_t; ++DEFINE_XEN_GUEST_HANDLE(pm_px_stat_t); ++ ++struct pm_cx_stat { ++ uint32_t nr; /* entry nr in triggers & residencies, including C0 */ ++ uint32_t last; /* last Cx state */ ++ uint64_aligned_t idle_time; /* idle time from boot */ ++ XEN_GUEST_HANDLE_64(uint64) triggers; /* Cx trigger counts */ ++ XEN_GUEST_HANDLE_64(uint64) residencies; /* Cx residencies */ ++}; ++ ++struct xen_sysctl_get_pmstat { ++#define PMSTAT_CATEGORY_MASK 0xf0 ++#define PMSTAT_PX 0x10 ++#define PMSTAT_CX 0x20 ++#define PMSTAT_get_max_px (PMSTAT_PX | 0x1) ++#define PMSTAT_get_pxstat (PMSTAT_PX | 0x2) ++#define PMSTAT_reset_pxstat (PMSTAT_PX | 0x3) ++#define PMSTAT_get_max_cx (PMSTAT_CX | 0x1) ++#define PMSTAT_get_cxstat (PMSTAT_CX | 0x2) ++#define PMSTAT_reset_cxstat (PMSTAT_CX | 0x3) ++ uint32_t type; ++ uint32_t cpuid; ++ union { ++ struct pm_px_stat getpx; ++ struct pm_cx_stat getcx; ++ /* other struct for tx, etc */ ++ } u; ++}; ++typedef struct xen_sysctl_get_pmstat xen_sysctl_get_pmstat_t; ++DEFINE_XEN_GUEST_HANDLE(xen_sysctl_get_pmstat_t); ++ ++/* ++ * Status codes. Must be greater than 0 to avoid confusing ++ * sysctl callers that see 0 as a plain successful return. ++ */ ++#define XEN_CPU_HOTPLUG_STATUS_OFFLINE 1 ++#define XEN_CPU_HOTPLUG_STATUS_ONLINE 2 ++#define XEN_CPU_HOTPLUG_STATUS_NEW 3 ++ ++#define XEN_SYSCTL_cpu_hotplug 11 ++struct xen_sysctl_cpu_hotplug { ++ /* IN variables */ ++ uint32_t cpu; /* Physical cpu. */ ++#define XEN_SYSCTL_CPU_HOTPLUG_ONLINE 0 ++#define XEN_SYSCTL_CPU_HOTPLUG_OFFLINE 1 ++#define XEN_SYSCTL_CPU_HOTPLUG_STATUS 2 ++ uint32_t op; /* hotplug opcode */ ++}; ++typedef struct xen_sysctl_cpu_hotplug xen_sysctl_cpu_hotplug_t; ++DEFINE_XEN_GUEST_HANDLE(xen_sysctl_cpu_hotplug_t); ++ ++/* ++ * Get/set xen power management, include ++ * 1. cpufreq governors and related parameters ++ */ ++#define XEN_SYSCTL_pm_op 12 ++struct xen_userspace { ++ uint32_t scaling_setspeed; ++}; ++typedef struct xen_userspace xen_userspace_t; ++ ++struct xen_ondemand { ++ uint32_t sampling_rate_max; ++ uint32_t sampling_rate_min; ++ ++ uint32_t sampling_rate; ++ uint32_t up_threshold; ++}; ++typedef struct xen_ondemand xen_ondemand_t; ++ ++/* ++ * cpufreq para name of this structure named ++ * same as sysfs file name of native linux ++ */ ++#define CPUFREQ_NAME_LEN 16 ++struct xen_get_cpufreq_para { ++ /* IN/OUT variable */ ++ uint32_t cpu_num; ++ uint32_t freq_num; ++ uint32_t gov_num; ++ ++ /* for all governors */ ++ /* OUT variable */ ++ XEN_GUEST_HANDLE_64(uint32) affected_cpus; ++ XEN_GUEST_HANDLE_64(uint32) scaling_available_frequencies; ++ XEN_GUEST_HANDLE_64(char) scaling_available_governors; ++ char scaling_driver[CPUFREQ_NAME_LEN]; ++ ++ uint32_t cpuinfo_cur_freq; ++ uint32_t cpuinfo_max_freq; ++ uint32_t cpuinfo_min_freq; ++ uint32_t scaling_cur_freq; ++ ++ char scaling_governor[CPUFREQ_NAME_LEN]; ++ uint32_t scaling_max_freq; ++ uint32_t scaling_min_freq; ++ ++ /* for specific governor */ ++ union { ++ struct xen_userspace userspace; ++ struct xen_ondemand ondemand; ++ } u; ++}; ++ ++struct xen_set_cpufreq_gov { ++ char scaling_governor[CPUFREQ_NAME_LEN]; ++}; ++ ++struct xen_set_cpufreq_para { ++ #define SCALING_MAX_FREQ 1 ++ #define SCALING_MIN_FREQ 2 ++ #define SCALING_SETSPEED 3 ++ #define SAMPLING_RATE 4 ++ #define UP_THRESHOLD 5 ++ ++ uint32_t ctrl_type; ++ uint32_t ctrl_value; ++}; ++ ++/* Get physical CPU topology information. */ ++#define INVALID_TOPOLOGY_ID (~0U) ++struct xen_get_cputopo { ++ /* IN: maximum addressable entry in ++ * the caller-provided cpu_to_core/socket. ++ */ ++ uint32_t max_cpus; ++ XEN_GUEST_HANDLE_64(uint32) cpu_to_core; ++ XEN_GUEST_HANDLE_64(uint32) cpu_to_socket; ++ ++ /* OUT: number of cpus returned ++ * If OUT is greater than IN then the cpu_to_core/socket is truncated! ++ */ ++ uint32_t nr_cpus; ++}; ++ ++struct xen_sysctl_pm_op { ++ #define PM_PARA_CATEGORY_MASK 0xf0 ++ #define CPUFREQ_PARA 0x10 ++ ++ /* cpufreq command type */ ++ #define GET_CPUFREQ_PARA (CPUFREQ_PARA | 0x01) ++ #define SET_CPUFREQ_GOV (CPUFREQ_PARA | 0x02) ++ #define SET_CPUFREQ_PARA (CPUFREQ_PARA | 0x03) ++ #define GET_CPUFREQ_AVGFREQ (CPUFREQ_PARA | 0x04) ++ ++ /* get CPU topology */ ++ #define XEN_SYSCTL_pm_op_get_cputopo 0x20 ++ ++ /* set/reset scheduler power saving option */ ++ #define XEN_SYSCTL_pm_op_set_sched_opt_smt 0x21 ++ ++ /* cpuidle max_cstate access command */ ++ #define XEN_SYSCTL_pm_op_get_max_cstate 0x22 ++ #define XEN_SYSCTL_pm_op_set_max_cstate 0x23 ++ ++ /* set scheduler migration cost value */ ++ #define XEN_SYSCTL_pm_op_set_vcpu_migration_delay 0x24 ++ #define XEN_SYSCTL_pm_op_get_vcpu_migration_delay 0x25 ++ ++ uint32_t cmd; ++ uint32_t cpuid; ++ union { ++ struct xen_get_cpufreq_para get_para; ++ struct xen_set_cpufreq_gov set_gov; ++ struct xen_set_cpufreq_para set_para; ++ uint64_aligned_t get_avgfreq; ++ struct xen_get_cputopo get_topo; ++ uint32_t set_sched_opt_smt; ++ uint32_t get_max_cstate; ++ uint32_t set_max_cstate; ++ uint32_t get_vcpu_migration_delay; ++ uint32_t set_vcpu_migration_delay; ++ } u; ++}; ++ ++#define XEN_SYSCTL_page_offline_op 14 ++struct xen_sysctl_page_offline_op { ++ /* IN: range of page to be offlined */ ++#define sysctl_page_offline 1 ++#define sysctl_page_online 2 ++#define sysctl_query_page_offline 3 ++ uint32_t cmd; ++ uint32_t start; ++ uint32_t end; ++ /* OUT: result of page offline request */ ++ /* ++ * bit 0~15: result flags ++ * bit 16~31: owner ++ */ ++ XEN_GUEST_HANDLE(uint32) status; ++}; ++ ++#define PG_OFFLINE_STATUS_MASK (0xFFUL) ++ ++/* The result is invalid, i.e. HV does not handle it */ ++#define PG_OFFLINE_INVALID (0x1UL << 0) ++ ++#define PG_OFFLINE_OFFLINED (0x1UL << 1) ++#define PG_OFFLINE_PENDING (0x1UL << 2) ++#define PG_OFFLINE_FAILED (0x1UL << 3) ++ ++#define PG_ONLINE_FAILED PG_OFFLINE_FAILED ++#define PG_ONLINE_ONLINED PG_OFFLINE_OFFLINED ++ ++#define PG_OFFLINE_STATUS_OFFLINED (0x1UL << 1) ++#define PG_OFFLINE_STATUS_ONLINE (0x1UL << 2) ++#define PG_OFFLINE_STATUS_OFFLINE_PENDING (0x1UL << 3) ++#define PG_OFFLINE_STATUS_BROKEN (0x1UL << 4) ++ ++#define PG_OFFLINE_MISC_MASK (0xFFUL << 4) ++ ++/* only valid when PG_OFFLINE_FAILED */ ++#define PG_OFFLINE_XENPAGE (0x1UL << 8) ++#define PG_OFFLINE_DOM0PAGE (0x1UL << 9) ++#define PG_OFFLINE_ANONYMOUS (0x1UL << 10) ++#define PG_OFFLINE_NOT_CONV_RAM (0x1UL << 11) ++#define PG_OFFLINE_OWNED (0x1UL << 12) ++ ++#define PG_OFFLINE_BROKEN (0x1UL << 13) ++#define PG_ONLINE_BROKEN PG_OFFLINE_BROKEN ++ ++#define PG_OFFLINE_OWNER_SHIFT 16 ++ ++#define XEN_SYSCTL_lockprof_op 15 ++/* Sub-operations: */ ++#define XEN_SYSCTL_LOCKPROF_reset 1 /* Reset all profile data to zero. */ ++#define XEN_SYSCTL_LOCKPROF_query 2 /* Get lock profile information. */ ++/* Record-type: */ ++#define LOCKPROF_TYPE_GLOBAL 0 /* global lock, idx meaningless */ ++#define LOCKPROF_TYPE_PERDOM 1 /* per-domain lock, idx is domid */ ++#define LOCKPROF_TYPE_N 2 /* number of types */ ++struct xen_sysctl_lockprof_data { ++ char name[40]; /* lock name (may include up to 2 %d specifiers) */ ++ int32_t type; /* LOCKPROF_TYPE_??? */ ++ int32_t idx; /* index (e.g. domain id) */ ++ uint64_aligned_t lock_cnt; /* # of locking succeeded */ ++ uint64_aligned_t block_cnt; /* # of wait for lock */ ++ uint64_aligned_t lock_time; /* nsecs lock held */ ++ uint64_aligned_t block_time; /* nsecs waited for lock */ ++}; ++typedef struct xen_sysctl_lockprof_data xen_sysctl_lockprof_data_t; ++DEFINE_XEN_GUEST_HANDLE(xen_sysctl_lockprof_data_t); ++struct xen_sysctl_lockprof_op { ++ /* IN variables. */ ++ uint32_t cmd; /* XEN_SYSCTL_LOCKPROF_??? */ ++ uint32_t max_elem; /* size of output buffer */ ++ /* OUT variables (query only). */ ++ uint32_t nr_elem; /* number of elements available */ ++ uint64_aligned_t time; /* nsecs of profile measurement */ ++ /* profile information (or NULL) */ ++ XEN_GUEST_HANDLE_64(xen_sysctl_lockprof_data_t) data; ++}; ++typedef struct xen_sysctl_lockprof_op xen_sysctl_lockprof_op_t; ++DEFINE_XEN_GUEST_HANDLE(xen_sysctl_lockprof_op_t); ++ ++struct xen_sysctl { ++ uint32_t cmd; ++ uint32_t interface_version; /* XEN_SYSCTL_INTERFACE_VERSION */ ++ union { ++ struct xen_sysctl_readconsole readconsole; ++ struct xen_sysctl_tbuf_op tbuf_op; ++ struct xen_sysctl_physinfo physinfo; ++ struct xen_sysctl_sched_id sched_id; ++ struct xen_sysctl_perfc_op perfc_op; ++ struct xen_sysctl_getdomaininfolist getdomaininfolist; ++ struct xen_sysctl_debug_keys debug_keys; ++ struct xen_sysctl_getcpuinfo getcpuinfo; ++ struct xen_sysctl_availheap availheap; ++ struct xen_sysctl_get_pmstat get_pmstat; ++ struct xen_sysctl_cpu_hotplug cpu_hotplug; ++ struct xen_sysctl_pm_op pm_op; ++ struct xen_sysctl_page_offline_op page_offline; ++ struct xen_sysctl_lockprof_op lockprof_op; ++ uint8_t pad[128]; ++ } u; ++}; ++typedef struct xen_sysctl xen_sysctl_t; ++DEFINE_XEN_GUEST_HANDLE(xen_sysctl_t); ++ ++#endif /* __XEN_PUBLIC_SYSCTL_H__ */ ++ ++/* ++ * Local variables: ++ * mode: C ++ * c-set-style: "BSD" ++ * c-basic-offset: 4 ++ * tab-width: 4 ++ * indent-tabs-mode: nil ++ * End: ++ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/include/xen/interface/tmem.h 2010-01-04 11:56:34.000000000 +0100 +@@ -0,0 +1,144 @@ ++/****************************************************************************** ++ * tmem.h ++ * ++ * Guest OS interface to Xen Transcendent Memory. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to ++ * deal in the Software without restriction, including without limitation the ++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ++ * DEALINGS IN THE SOFTWARE. ++ * ++ * Copyright (c) 2004, K A Fraser ++ */ ++ ++#ifndef __XEN_PUBLIC_TMEM_H__ ++#define __XEN_PUBLIC_TMEM_H__ ++ ++#include "xen.h" ++ ++/* Commands to HYPERVISOR_tmem_op() */ ++#define TMEM_CONTROL 0 ++#define TMEM_NEW_POOL 1 ++#define TMEM_DESTROY_POOL 2 ++#define TMEM_NEW_PAGE 3 ++#define TMEM_PUT_PAGE 4 ++#define TMEM_GET_PAGE 5 ++#define TMEM_FLUSH_PAGE 6 ++#define TMEM_FLUSH_OBJECT 7 ++#define TMEM_READ 8 ++#define TMEM_WRITE 9 ++#define TMEM_XCHG 10 ++ ++/* Privileged commands to HYPERVISOR_tmem_op() */ ++#define TMEM_AUTH 101 ++#define TMEM_RESTORE_NEW 102 ++ ++/* Subops for HYPERVISOR_tmem_op(TMEM_CONTROL) */ ++#define TMEMC_THAW 0 ++#define TMEMC_FREEZE 1 ++#define TMEMC_FLUSH 2 ++#define TMEMC_DESTROY 3 ++#define TMEMC_LIST 4 ++#define TMEMC_SET_WEIGHT 5 ++#define TMEMC_SET_CAP 6 ++#define TMEMC_SET_COMPRESS 7 ++#define TMEMC_QUERY_FREEABLE_MB 8 ++#define TMEMC_SAVE_BEGIN 10 ++#define TMEMC_SAVE_GET_VERSION 11 ++#define TMEMC_SAVE_GET_MAXPOOLS 12 ++#define TMEMC_SAVE_GET_CLIENT_WEIGHT 13 ++#define TMEMC_SAVE_GET_CLIENT_CAP 14 ++#define TMEMC_SAVE_GET_CLIENT_FLAGS 15 ++#define TMEMC_SAVE_GET_POOL_FLAGS 16 ++#define TMEMC_SAVE_GET_POOL_NPAGES 17 ++#define TMEMC_SAVE_GET_POOL_UUID 18 ++#define TMEMC_SAVE_GET_NEXT_PAGE 19 ++#define TMEMC_SAVE_GET_NEXT_INV 20 ++#define TMEMC_SAVE_END 21 ++#define TMEMC_RESTORE_BEGIN 30 ++#define TMEMC_RESTORE_PUT_PAGE 32 ++#define TMEMC_RESTORE_FLUSH_PAGE 33 ++ ++/* Bits for HYPERVISOR_tmem_op(TMEM_NEW_POOL) */ ++#define TMEM_POOL_PERSIST 1 ++#define TMEM_POOL_SHARED 2 ++#define TMEM_POOL_PAGESIZE_SHIFT 4 ++#define TMEM_POOL_PAGESIZE_MASK 0xf ++#define TMEM_POOL_VERSION_SHIFT 24 ++#define TMEM_POOL_VERSION_MASK 0xff ++ ++/* Bits for client flags (save/restore) */ ++#define TMEM_CLIENT_COMPRESS 1 ++#define TMEM_CLIENT_FROZEN 2 ++ ++/* Special errno values */ ++#define EFROZEN 1000 ++#define EEMPTY 1001 ++ ++ ++#ifndef __ASSEMBLY__ ++typedef xen_pfn_t tmem_cli_mfn_t; ++typedef XEN_GUEST_HANDLE(char) tmem_cli_va_t; ++struct tmem_op { ++ uint32_t cmd; ++ int32_t pool_id; ++ union { ++ struct { ++ uint64_t uuid[2]; ++ uint32_t flags; ++ uint32_t arg1; ++ } new; /* for cmd == TMEM_NEW_POOL, TMEM_AUTH, TMEM_RESTORE_NEW */ ++ struct { ++ uint32_t subop; ++ uint32_t cli_id; ++ uint32_t arg1; ++ uint32_t arg2; ++ uint64_t arg3; ++ tmem_cli_va_t buf; ++ } ctrl; /* for cmd == TMEM_CONTROL */ ++ struct { ++ ++ uint64_t object; ++ uint32_t index; ++ uint32_t tmem_offset; ++ uint32_t pfn_offset; ++ uint32_t len; ++ tmem_cli_mfn_t cmfn; /* client machine page frame */ ++ } gen; /* for all other cmd ("generic") */ ++ } u; ++}; ++typedef struct tmem_op tmem_op_t; ++DEFINE_XEN_GUEST_HANDLE(tmem_op_t); ++ ++struct tmem_handle { ++ uint32_t pool_id; ++ uint32_t index; ++ uint64_t oid; ++}; ++ ++#endif ++ ++#endif /* __XEN_PUBLIC_TMEM_H__ */ ++ ++/* ++ * Local variables: ++ * mode: C ++ * c-set-style: "BSD" ++ * c-basic-offset: 4 ++ * tab-width: 4 ++ * indent-tabs-mode: nil ++ * End: ++ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/include/xen/interface/trace.h 2009-06-23 09:28:21.000000000 +0200 +@@ -0,0 +1,208 @@ ++/****************************************************************************** ++ * include/public/trace.h ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to ++ * deal in the Software without restriction, including without limitation the ++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ++ * DEALINGS IN THE SOFTWARE. ++ * ++ * Mark Williamson, (C) 2004 Intel Research Cambridge ++ * Copyright (C) 2005 Bin Ren ++ */ ++ ++#ifndef __XEN_PUBLIC_TRACE_H__ ++#define __XEN_PUBLIC_TRACE_H__ ++ ++#define TRACE_EXTRA_MAX 7 ++#define TRACE_EXTRA_SHIFT 28 ++ ++/* Trace classes */ ++#define TRC_CLS_SHIFT 16 ++#define TRC_GEN 0x0001f000 /* General trace */ ++#define TRC_SCHED 0x0002f000 /* Xen Scheduler trace */ ++#define TRC_DOM0OP 0x0004f000 /* Xen DOM0 operation trace */ ++#define TRC_HVM 0x0008f000 /* Xen HVM trace */ ++#define TRC_MEM 0x0010f000 /* Xen memory trace */ ++#define TRC_PV 0x0020f000 /* Xen PV traces */ ++#define TRC_SHADOW 0x0040f000 /* Xen shadow tracing */ ++#define TRC_PM 0x0080f000 /* Xen power management trace */ ++#define TRC_ALL 0x0ffff000 ++#define TRC_HD_TO_EVENT(x) ((x)&0x0fffffff) ++#define TRC_HD_CYCLE_FLAG (1UL<<31) ++#define TRC_HD_INCLUDES_CYCLE_COUNT(x) ( !!( (x) & TRC_HD_CYCLE_FLAG ) ) ++#define TRC_HD_EXTRA(x) (((x)>>TRACE_EXTRA_SHIFT)&TRACE_EXTRA_MAX) ++ ++/* Trace subclasses */ ++#define TRC_SUBCLS_SHIFT 12 ++ ++/* trace subclasses for SVM */ ++#define TRC_HVM_ENTRYEXIT 0x00081000 /* VMENTRY and #VMEXIT */ ++#define TRC_HVM_HANDLER 0x00082000 /* various HVM handlers */ ++ ++#define TRC_SCHED_MIN 0x00021000 /* Just runstate changes */ ++#define TRC_SCHED_VERBOSE 0x00028000 /* More inclusive scheduling */ ++ ++/* Trace events per class */ ++#define TRC_LOST_RECORDS (TRC_GEN + 1) ++#define TRC_TRACE_WRAP_BUFFER (TRC_GEN + 2) ++#define TRC_TRACE_CPU_CHANGE (TRC_GEN + 3) ++#define TRC_TRACE_IRQ (TRC_GEN + 4) ++ ++#define TRC_SCHED_RUNSTATE_CHANGE (TRC_SCHED_MIN + 1) ++#define TRC_SCHED_CONTINUE_RUNNING (TRC_SCHED_MIN + 2) ++#define TRC_SCHED_DOM_ADD (TRC_SCHED_VERBOSE + 1) ++#define TRC_SCHED_DOM_REM (TRC_SCHED_VERBOSE + 2) ++#define TRC_SCHED_SLEEP (TRC_SCHED_VERBOSE + 3) ++#define TRC_SCHED_WAKE (TRC_SCHED_VERBOSE + 4) ++#define TRC_SCHED_YIELD (TRC_SCHED_VERBOSE + 5) ++#define TRC_SCHED_BLOCK (TRC_SCHED_VERBOSE + 6) ++#define TRC_SCHED_SHUTDOWN (TRC_SCHED_VERBOSE + 7) ++#define TRC_SCHED_CTL (TRC_SCHED_VERBOSE + 8) ++#define TRC_SCHED_ADJDOM (TRC_SCHED_VERBOSE + 9) ++#define TRC_SCHED_SWITCH (TRC_SCHED_VERBOSE + 10) ++#define TRC_SCHED_S_TIMER_FN (TRC_SCHED_VERBOSE + 11) ++#define TRC_SCHED_T_TIMER_FN (TRC_SCHED_VERBOSE + 12) ++#define TRC_SCHED_DOM_TIMER_FN (TRC_SCHED_VERBOSE + 13) ++#define TRC_SCHED_SWITCH_INFPREV (TRC_SCHED_VERBOSE + 14) ++#define TRC_SCHED_SWITCH_INFNEXT (TRC_SCHED_VERBOSE + 15) ++ ++#define TRC_MEM_PAGE_GRANT_MAP (TRC_MEM + 1) ++#define TRC_MEM_PAGE_GRANT_UNMAP (TRC_MEM + 2) ++#define TRC_MEM_PAGE_GRANT_TRANSFER (TRC_MEM + 3) ++ ++#define TRC_PV_HYPERCALL (TRC_PV + 1) ++#define TRC_PV_TRAP (TRC_PV + 3) ++#define TRC_PV_PAGE_FAULT (TRC_PV + 4) ++#define TRC_PV_FORCED_INVALID_OP (TRC_PV + 5) ++#define TRC_PV_EMULATE_PRIVOP (TRC_PV + 6) ++#define TRC_PV_EMULATE_4GB (TRC_PV + 7) ++#define TRC_PV_MATH_STATE_RESTORE (TRC_PV + 8) ++#define TRC_PV_PAGING_FIXUP (TRC_PV + 9) ++#define TRC_PV_GDT_LDT_MAPPING_FAULT (TRC_PV + 10) ++#define TRC_PV_PTWR_EMULATION (TRC_PV + 11) ++#define TRC_PV_PTWR_EMULATION_PAE (TRC_PV + 12) ++ /* Indicates that addresses in trace record are 64 bits */ ++#define TRC_64_FLAG (0x100) ++ ++#define TRC_SHADOW_NOT_SHADOW (TRC_SHADOW + 1) ++#define TRC_SHADOW_FAST_PROPAGATE (TRC_SHADOW + 2) ++#define TRC_SHADOW_FAST_MMIO (TRC_SHADOW + 3) ++#define TRC_SHADOW_FALSE_FAST_PATH (TRC_SHADOW + 4) ++#define TRC_SHADOW_MMIO (TRC_SHADOW + 5) ++#define TRC_SHADOW_FIXUP (TRC_SHADOW + 6) ++#define TRC_SHADOW_DOMF_DYING (TRC_SHADOW + 7) ++#define TRC_SHADOW_EMULATE (TRC_SHADOW + 8) ++#define TRC_SHADOW_EMULATE_UNSHADOW_USER (TRC_SHADOW + 9) ++#define TRC_SHADOW_EMULATE_UNSHADOW_EVTINJ (TRC_SHADOW + 10) ++#define TRC_SHADOW_EMULATE_UNSHADOW_UNHANDLED (TRC_SHADOW + 11) ++#define TRC_SHADOW_WRMAP_BF (TRC_SHADOW + 12) ++#define TRC_SHADOW_PREALLOC_UNPIN (TRC_SHADOW + 13) ++#define TRC_SHADOW_RESYNC_FULL (TRC_SHADOW + 14) ++#define TRC_SHADOW_RESYNC_ONLY (TRC_SHADOW + 15) ++ ++/* trace events per subclass */ ++#define TRC_HVM_VMENTRY (TRC_HVM_ENTRYEXIT + 0x01) ++#define TRC_HVM_VMEXIT (TRC_HVM_ENTRYEXIT + 0x02) ++#define TRC_HVM_VMEXIT64 (TRC_HVM_ENTRYEXIT + TRC_64_FLAG + 0x02) ++#define TRC_HVM_PF_XEN (TRC_HVM_HANDLER + 0x01) ++#define TRC_HVM_PF_XEN64 (TRC_HVM_HANDLER + TRC_64_FLAG + 0x01) ++#define TRC_HVM_PF_INJECT (TRC_HVM_HANDLER + 0x02) ++#define TRC_HVM_PF_INJECT64 (TRC_HVM_HANDLER + TRC_64_FLAG + 0x02) ++#define TRC_HVM_INJ_EXC (TRC_HVM_HANDLER + 0x03) ++#define TRC_HVM_INJ_VIRQ (TRC_HVM_HANDLER + 0x04) ++#define TRC_HVM_REINJ_VIRQ (TRC_HVM_HANDLER + 0x05) ++#define TRC_HVM_IO_READ (TRC_HVM_HANDLER + 0x06) ++#define TRC_HVM_IO_WRITE (TRC_HVM_HANDLER + 0x07) ++#define TRC_HVM_CR_READ (TRC_HVM_HANDLER + 0x08) ++#define TRC_HVM_CR_READ64 (TRC_HVM_HANDLER + TRC_64_FLAG + 0x08) ++#define TRC_HVM_CR_WRITE (TRC_HVM_HANDLER + 0x09) ++#define TRC_HVM_CR_WRITE64 (TRC_HVM_HANDLER + TRC_64_FLAG + 0x09) ++#define TRC_HVM_DR_READ (TRC_HVM_HANDLER + 0x0A) ++#define TRC_HVM_DR_WRITE (TRC_HVM_HANDLER + 0x0B) ++#define TRC_HVM_MSR_READ (TRC_HVM_HANDLER + 0x0C) ++#define TRC_HVM_MSR_WRITE (TRC_HVM_HANDLER + 0x0D) ++#define TRC_HVM_CPUID (TRC_HVM_HANDLER + 0x0E) ++#define TRC_HVM_INTR (TRC_HVM_HANDLER + 0x0F) ++#define TRC_HVM_NMI (TRC_HVM_HANDLER + 0x10) ++#define TRC_HVM_SMI (TRC_HVM_HANDLER + 0x11) ++#define TRC_HVM_VMMCALL (TRC_HVM_HANDLER + 0x12) ++#define TRC_HVM_HLT (TRC_HVM_HANDLER + 0x13) ++#define TRC_HVM_INVLPG (TRC_HVM_HANDLER + 0x14) ++#define TRC_HVM_INVLPG64 (TRC_HVM_HANDLER + TRC_64_FLAG + 0x14) ++#define TRC_HVM_MCE (TRC_HVM_HANDLER + 0x15) ++#define TRC_HVM_IOPORT_READ (TRC_HVM_HANDLER + 0x16) ++#define TRC_HVM_IOMEM_READ (TRC_HVM_HANDLER + 0x17) ++#define TRC_HVM_CLTS (TRC_HVM_HANDLER + 0x18) ++#define TRC_HVM_LMSW (TRC_HVM_HANDLER + 0x19) ++#define TRC_HVM_LMSW64 (TRC_HVM_HANDLER + TRC_64_FLAG + 0x19) ++#define TRC_HVM_INTR_WINDOW (TRC_HVM_HANDLER + 0x20) ++#define TRC_HVM_IOPORT_WRITE (TRC_HVM_HANDLER + 0x216) ++#define TRC_HVM_IOMEM_WRITE (TRC_HVM_HANDLER + 0x217) ++ ++/* trace subclasses for power management */ ++#define TRC_PM_FREQ 0x00801000 /* xen cpu freq events */ ++#define TRC_PM_IDLE 0x00802000 /* xen cpu idle events */ ++ ++/* trace events for per class */ ++#define TRC_PM_FREQ_CHANGE (TRC_PM_FREQ + 0x01) ++#define TRC_PM_IDLE_ENTRY (TRC_PM_IDLE + 0x01) ++#define TRC_PM_IDLE_EXIT (TRC_PM_IDLE + 0x02) ++ ++/* This structure represents a single trace buffer record. */ ++struct t_rec { ++ uint32_t event:28; ++ uint32_t extra_u32:3; /* # entries in trailing extra_u32[] array */ ++ uint32_t cycles_included:1; /* u.cycles or u.no_cycles? */ ++ union { ++ struct { ++ uint32_t cycles_lo, cycles_hi; /* cycle counter timestamp */ ++ uint32_t extra_u32[7]; /* event data items */ ++ } cycles; ++ struct { ++ uint32_t extra_u32[7]; /* event data items */ ++ } nocycles; ++ } u; ++}; ++ ++/* ++ * This structure contains the metadata for a single trace buffer. The head ++ * field, indexes into an array of struct t_rec's. ++ */ ++struct t_buf { ++ /* Assume the data buffer size is X. X is generally not a power of 2. ++ * CONS and PROD are incremented modulo (2*X): ++ * 0 <= cons < 2*X ++ * 0 <= prod < 2*X ++ * This is done because addition modulo X breaks at 2^32 when X is not a ++ * power of 2: ++ * (((2^32 - 1) % X) + 1) % X != (2^32) % X ++ */ ++ uint32_t cons; /* Offset of next item to be consumed by control tools. */ ++ uint32_t prod; /* Offset of next item to be produced by Xen. */ ++ /* Records follow immediately after the meta-data header. */ ++}; ++ ++#endif /* __XEN_PUBLIC_TRACE_H__ */ ++ ++/* ++ * Local variables: ++ * mode: C ++ * c-set-style: "BSD" ++ * c-basic-offset: 4 ++ * tab-width: 4 ++ * indent-tabs-mode: nil ++ * End: ++ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/include/xen/interface/xen-compat.h 2010-01-04 11:56:34.000000000 +0100 +@@ -0,0 +1,44 @@ ++/****************************************************************************** ++ * xen-compat.h ++ * ++ * Guest OS interface to Xen. Compatibility layer. ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to ++ * deal in the Software without restriction, including without limitation the ++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ++ * DEALINGS IN THE SOFTWARE. ++ * ++ * Copyright (c) 2006, Christian Limpach ++ */ ++ ++#ifndef __XEN_PUBLIC_XEN_COMPAT_H__ ++#define __XEN_PUBLIC_XEN_COMPAT_H__ ++ ++#define __XEN_LATEST_INTERFACE_VERSION__ 0x0003020a ++ ++#if defined(__XEN__) || defined(__XEN_TOOLS__) ++/* Xen is built with matching headers and implements the latest interface. */ ++#define __XEN_INTERFACE_VERSION__ __XEN_LATEST_INTERFACE_VERSION__ ++#elif !defined(__XEN_INTERFACE_VERSION__) ++/* Guests which do not specify a version get the legacy interface. */ ++#define __XEN_INTERFACE_VERSION__ 0x00000000 ++#endif ++ ++#if __XEN_INTERFACE_VERSION__ > __XEN_LATEST_INTERFACE_VERSION__ ++#error "These header files do not support the requested interface version." ++#endif ++ ++#endif /* __XEN_PUBLIC_XEN_COMPAT_H__ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/include/xen/interface/xenoprof.h 2007-06-12 13:14:19.000000000 +0200 +@@ -0,0 +1,138 @@ ++/****************************************************************************** ++ * xenoprof.h ++ * ++ * Interface for enabling system wide profiling based on hardware performance ++ * counters ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to ++ * deal in the Software without restriction, including without limitation the ++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ++ * DEALINGS IN THE SOFTWARE. ++ * ++ * Copyright (C) 2005 Hewlett-Packard Co. ++ * Written by Aravind Menon & Jose Renato Santos ++ */ ++ ++#ifndef __XEN_PUBLIC_XENOPROF_H__ ++#define __XEN_PUBLIC_XENOPROF_H__ ++ ++#include "xen.h" ++ ++/* ++ * Commands to HYPERVISOR_xenoprof_op(). ++ */ ++#define XENOPROF_init 0 ++#define XENOPROF_reset_active_list 1 ++#define XENOPROF_reset_passive_list 2 ++#define XENOPROF_set_active 3 ++#define XENOPROF_set_passive 4 ++#define XENOPROF_reserve_counters 5 ++#define XENOPROF_counter 6 ++#define XENOPROF_setup_events 7 ++#define XENOPROF_enable_virq 8 ++#define XENOPROF_start 9 ++#define XENOPROF_stop 10 ++#define XENOPROF_disable_virq 11 ++#define XENOPROF_release_counters 12 ++#define XENOPROF_shutdown 13 ++#define XENOPROF_get_buffer 14 ++#define XENOPROF_set_backtrace 15 ++#define XENOPROF_last_op 15 ++ ++#define MAX_OPROF_EVENTS 32 ++#define MAX_OPROF_DOMAINS 25 ++#define XENOPROF_CPU_TYPE_SIZE 64 ++ ++/* Xenoprof performance events (not Xen events) */ ++struct event_log { ++ uint64_t eip; ++ uint8_t mode; ++ uint8_t event; ++}; ++ ++/* PC value that indicates a special code */ ++#define XENOPROF_ESCAPE_CODE ~0UL ++/* Transient events for the xenoprof->oprofile cpu buf */ ++#define XENOPROF_TRACE_BEGIN 1 ++ ++/* Xenoprof buffer shared between Xen and domain - 1 per VCPU */ ++struct xenoprof_buf { ++ uint32_t event_head; ++ uint32_t event_tail; ++ uint32_t event_size; ++ uint32_t vcpu_id; ++ uint64_t xen_samples; ++ uint64_t kernel_samples; ++ uint64_t user_samples; ++ uint64_t lost_samples; ++ struct event_log event_log[1]; ++}; ++#ifndef __XEN__ ++typedef struct xenoprof_buf xenoprof_buf_t; ++DEFINE_XEN_GUEST_HANDLE(xenoprof_buf_t); ++#endif ++ ++struct xenoprof_init { ++ int32_t num_events; ++ int32_t is_primary; ++ char cpu_type[XENOPROF_CPU_TYPE_SIZE]; ++}; ++typedef struct xenoprof_init xenoprof_init_t; ++DEFINE_XEN_GUEST_HANDLE(xenoprof_init_t); ++ ++struct xenoprof_get_buffer { ++ int32_t max_samples; ++ int32_t nbuf; ++ int32_t bufsize; ++ uint64_t buf_gmaddr; ++}; ++typedef struct xenoprof_get_buffer xenoprof_get_buffer_t; ++DEFINE_XEN_GUEST_HANDLE(xenoprof_get_buffer_t); ++ ++struct xenoprof_counter { ++ uint32_t ind; ++ uint64_t count; ++ uint32_t enabled; ++ uint32_t event; ++ uint32_t hypervisor; ++ uint32_t kernel; ++ uint32_t user; ++ uint64_t unit_mask; ++}; ++typedef struct xenoprof_counter xenoprof_counter_t; ++DEFINE_XEN_GUEST_HANDLE(xenoprof_counter_t); ++ ++typedef struct xenoprof_passive { ++ uint16_t domain_id; ++ int32_t max_samples; ++ int32_t nbuf; ++ int32_t bufsize; ++ uint64_t buf_gmaddr; ++} xenoprof_passive_t; ++DEFINE_XEN_GUEST_HANDLE(xenoprof_passive_t); ++ ++ ++#endif /* __XEN_PUBLIC_XENOPROF_H__ */ ++ ++/* ++ * Local variables: ++ * mode: C ++ * c-set-style: "BSD" ++ * c-basic-offset: 4 ++ * tab-width: 4 ++ * indent-tabs-mode: nil ++ * End: ++ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/include/xen/interface/xsm/acm.h 2010-01-04 11:56:34.000000000 +0100 +@@ -0,0 +1,223 @@ ++/* ++ * acm.h: Xen access control module interface defintions ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to ++ * deal in the Software without restriction, including without limitation the ++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ++ * DEALINGS IN THE SOFTWARE. ++ * ++ * Reiner Sailer ++ * Copyright (c) 2005, International Business Machines Corporation. ++ */ ++ ++#ifndef _XEN_PUBLIC_ACM_H ++#define _XEN_PUBLIC_ACM_H ++ ++#include "../xen.h" ++ ++/* default ssid reference value if not supplied */ ++#define ACM_DEFAULT_SSID 0x0 ++#define ACM_DEFAULT_LOCAL_SSID 0x0 ++ ++/* Internal ACM ERROR types */ ++#define ACM_OK 0 ++#define ACM_UNDEF -1 ++#define ACM_INIT_SSID_ERROR -2 ++#define ACM_INIT_SOID_ERROR -3 ++#define ACM_ERROR -4 ++ ++/* External ACCESS DECISIONS */ ++#define ACM_ACCESS_PERMITTED 0 ++#define ACM_ACCESS_DENIED -111 ++#define ACM_NULL_POINTER_ERROR -200 ++ ++/* ++ Error codes reported in when trying to test for a new policy ++ These error codes are reported in an array of tuples where ++ each error code is followed by a parameter describing the error ++ more closely, such as a domain id. ++*/ ++#define ACM_EVTCHN_SHARING_VIOLATION 0x100 ++#define ACM_GNTTAB_SHARING_VIOLATION 0x101 ++#define ACM_DOMAIN_LOOKUP 0x102 ++#define ACM_CHWALL_CONFLICT 0x103 ++#define ACM_SSIDREF_IN_USE 0x104 ++ ++ ++/* primary policy in lower 4 bits */ ++#define ACM_NULL_POLICY 0 ++#define ACM_CHINESE_WALL_POLICY 1 ++#define ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY 2 ++#define ACM_POLICY_UNDEFINED 15 ++ ++/* combinations have secondary policy component in higher 4bit */ ++#define ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY \ ++ ((ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY << 4) | ACM_CHINESE_WALL_POLICY) ++ ++/* policy: */ ++#define ACM_POLICY_NAME(X) \ ++ ((X) == (ACM_NULL_POLICY)) ? "NULL" : \ ++ ((X) == (ACM_CHINESE_WALL_POLICY)) ? "CHINESE WALL" : \ ++ ((X) == (ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY)) ? "SIMPLE TYPE ENFORCEMENT" : \ ++ ((X) == (ACM_CHINESE_WALL_AND_SIMPLE_TYPE_ENFORCEMENT_POLICY)) ? "CHINESE WALL AND SIMPLE TYPE ENFORCEMENT" : \ ++ "UNDEFINED" ++ ++/* the following policy versions must be increased ++ * whenever the interpretation of the related ++ * policy's data structure changes ++ */ ++#define ACM_POLICY_VERSION 4 ++#define ACM_CHWALL_VERSION 1 ++#define ACM_STE_VERSION 1 ++ ++/* defines a ssid reference used by xen */ ++typedef uint32_t ssidref_t; ++ ++/* hooks that are known to domains */ ++#define ACMHOOK_none 0 ++#define ACMHOOK_sharing 1 ++#define ACMHOOK_authorization 2 ++#define ACMHOOK_conflictset 3 ++ ++/* -------security policy relevant type definitions-------- */ ++ ++/* type identifier; compares to "equal" or "not equal" */ ++typedef uint16_t domaintype_t; ++ ++/* CHINESE WALL POLICY DATA STRUCTURES ++ * ++ * current accumulated conflict type set: ++ * When a domain is started and has a type that is in ++ * a conflict set, the conflicting types are incremented in ++ * the aggregate set. When a domain is destroyed, the ++ * conflicting types to its type are decremented. ++ * If a domain has multiple types, this procedure works over ++ * all those types. ++ * ++ * conflict_aggregate_set[i] holds the number of ++ * running domains that have a conflict with type i. ++ * ++ * running_types[i] holds the number of running domains ++ * that include type i in their ssidref-referenced type set ++ * ++ * conflict_sets[i][j] is "0" if type j has no conflict ++ * with type i and is "1" otherwise. ++ */ ++/* high-16 = version, low-16 = check magic */ ++#define ACM_MAGIC 0x0001debc ++ ++/* size of the SHA1 hash identifying the XML policy from which the ++ binary policy was created */ ++#define ACM_SHA1_HASH_SIZE 20 ++ ++/* each offset in bytes from start of the struct they ++ * are part of */ ++ ++/* V3 of the policy buffer aded a version structure */ ++struct acm_policy_version ++{ ++ uint32_t major; ++ uint32_t minor; ++}; ++ ++ ++/* each buffer consists of all policy information for ++ * the respective policy given in the policy code ++ * ++ * acm_policy_buffer, acm_chwall_policy_buffer, ++ * and acm_ste_policy_buffer need to stay 32-bit aligned ++ * because we create binary policies also with external ++ * tools that assume packed representations (e.g. the java tool) ++ */ ++struct acm_policy_buffer { ++ uint32_t magic; ++ uint32_t policy_version; /* ACM_POLICY_VERSION */ ++ uint32_t len; ++ uint32_t policy_reference_offset; ++ uint32_t primary_policy_code; ++ uint32_t primary_buffer_offset; ++ uint32_t secondary_policy_code; ++ uint32_t secondary_buffer_offset; ++ struct acm_policy_version xml_pol_version; /* add in V3 */ ++ uint8_t xml_policy_hash[ACM_SHA1_HASH_SIZE]; /* added in V4 */ ++}; ++ ++ ++struct acm_policy_reference_buffer { ++ uint32_t len; ++}; ++ ++struct acm_chwall_policy_buffer { ++ uint32_t policy_version; /* ACM_CHWALL_VERSION */ ++ uint32_t policy_code; ++ uint32_t chwall_max_types; ++ uint32_t chwall_max_ssidrefs; ++ uint32_t chwall_max_conflictsets; ++ uint32_t chwall_ssid_offset; ++ uint32_t chwall_conflict_sets_offset; ++ uint32_t chwall_running_types_offset; ++ uint32_t chwall_conflict_aggregate_offset; ++}; ++ ++struct acm_ste_policy_buffer { ++ uint32_t policy_version; /* ACM_STE_VERSION */ ++ uint32_t policy_code; ++ uint32_t ste_max_types; ++ uint32_t ste_max_ssidrefs; ++ uint32_t ste_ssid_offset; ++}; ++ ++struct acm_stats_buffer { ++ uint32_t magic; ++ uint32_t len; ++ uint32_t primary_policy_code; ++ uint32_t primary_stats_offset; ++ uint32_t secondary_policy_code; ++ uint32_t secondary_stats_offset; ++}; ++ ++struct acm_ste_stats_buffer { ++ uint32_t ec_eval_count; ++ uint32_t gt_eval_count; ++ uint32_t ec_denied_count; ++ uint32_t gt_denied_count; ++ uint32_t ec_cachehit_count; ++ uint32_t gt_cachehit_count; ++}; ++ ++struct acm_ssid_buffer { ++ uint32_t len; ++ ssidref_t ssidref; ++ uint32_t policy_reference_offset; ++ uint32_t primary_policy_code; ++ uint32_t primary_max_types; ++ uint32_t primary_types_offset; ++ uint32_t secondary_policy_code; ++ uint32_t secondary_max_types; ++ uint32_t secondary_types_offset; ++}; ++ ++#endif ++ ++/* ++ * Local variables: ++ * mode: C ++ * c-set-style: "BSD" ++ * c-basic-offset: 4 ++ * tab-width: 4 ++ * indent-tabs-mode: nil ++ * End: ++ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/include/xen/interface/xsm/acm_ops.h 2007-10-22 13:39:15.000000000 +0200 +@@ -0,0 +1,159 @@ ++/* ++ * acm_ops.h: Xen access control module hypervisor commands ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to ++ * deal in the Software without restriction, including without limitation the ++ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or ++ * sell copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ++ * DEALINGS IN THE SOFTWARE. ++ * ++ * Reiner Sailer ++ * Copyright (c) 2005,2006 International Business Machines Corporation. ++ */ ++ ++#ifndef __XEN_PUBLIC_ACM_OPS_H__ ++#define __XEN_PUBLIC_ACM_OPS_H__ ++ ++#include "../xen.h" ++#include "acm.h" ++ ++/* ++ * Make sure you increment the interface version whenever you modify this file! ++ * This makes sure that old versions of acm tools will stop working in a ++ * well-defined way (rather than crashing the machine, for instance). ++ */ ++#define ACM_INTERFACE_VERSION 0xAAAA000A ++ ++/************************************************************************/ ++ ++/* ++ * Prototype for this hypercall is: ++ * int acm_op(int cmd, void *args) ++ * @cmd == ACMOP_??? (access control module operation). ++ * @args == Operation-specific extra arguments (NULL if none). ++ */ ++ ++ ++#define ACMOP_setpolicy 1 ++struct acm_setpolicy { ++ /* IN */ ++ XEN_GUEST_HANDLE_64(void) pushcache; ++ uint32_t pushcache_size; ++}; ++ ++ ++#define ACMOP_getpolicy 2 ++struct acm_getpolicy { ++ /* IN */ ++ XEN_GUEST_HANDLE_64(void) pullcache; ++ uint32_t pullcache_size; ++}; ++ ++ ++#define ACMOP_dumpstats 3 ++struct acm_dumpstats { ++ /* IN */ ++ XEN_GUEST_HANDLE_64(void) pullcache; ++ uint32_t pullcache_size; ++}; ++ ++ ++#define ACMOP_getssid 4 ++#define ACM_GETBY_ssidref 1 ++#define ACM_GETBY_domainid 2 ++struct acm_getssid { ++ /* IN */ ++ uint32_t get_ssid_by; /* ACM_GETBY_* */ ++ union { ++ domaintype_t domainid; ++ ssidref_t ssidref; ++ } id; ++ XEN_GUEST_HANDLE_64(void) ssidbuf; ++ uint32_t ssidbuf_size; ++}; ++ ++#define ACMOP_getdecision 5 ++struct acm_getdecision { ++ /* IN */ ++ uint32_t get_decision_by1; /* ACM_GETBY_* */ ++ uint32_t get_decision_by2; /* ACM_GETBY_* */ ++ union { ++ domaintype_t domainid; ++ ssidref_t ssidref; ++ } id1; ++ union { ++ domaintype_t domainid; ++ ssidref_t ssidref; ++ } id2; ++ uint32_t hook; ++ /* OUT */ ++ uint32_t acm_decision; ++}; ++ ++ ++#define ACMOP_chgpolicy 6 ++struct acm_change_policy { ++ /* IN */ ++ XEN_GUEST_HANDLE_64(void) policy_pushcache; ++ uint32_t policy_pushcache_size; ++ XEN_GUEST_HANDLE_64(void) del_array; ++ uint32_t delarray_size; ++ XEN_GUEST_HANDLE_64(void) chg_array; ++ uint32_t chgarray_size; ++ /* OUT */ ++ /* array with error code */ ++ XEN_GUEST_HANDLE_64(void) err_array; ++ uint32_t errarray_size; ++}; ++ ++#define ACMOP_relabeldoms 7 ++struct acm_relabel_doms { ++ /* IN */ ++ XEN_GUEST_HANDLE_64(void) relabel_map; ++ uint32_t relabel_map_size; ++ /* OUT */ ++ XEN_GUEST_HANDLE_64(void) err_array; ++ uint32_t errarray_size; ++}; ++ ++/* future interface to Xen */ ++struct xen_acmctl { ++ uint32_t cmd; ++ uint32_t interface_version; ++ union { ++ struct acm_setpolicy setpolicy; ++ struct acm_getpolicy getpolicy; ++ struct acm_dumpstats dumpstats; ++ struct acm_getssid getssid; ++ struct acm_getdecision getdecision; ++ struct acm_change_policy change_policy; ++ struct acm_relabel_doms relabel_doms; ++ } u; ++}; ++ ++typedef struct xen_acmctl xen_acmctl_t; ++DEFINE_XEN_GUEST_HANDLE(xen_acmctl_t); ++ ++#endif /* __XEN_PUBLIC_ACM_OPS_H__ */ ++ ++/* ++ * Local variables: ++ * mode: C ++ * c-set-style: "BSD" ++ * c-basic-offset: 4 ++ * tab-width: 4 ++ * indent-tabs-mode: nil ++ * End: ++ */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/include/xen/interface/xsm/flask_op.h 2010-01-04 11:56:34.000000000 +0100 +@@ -0,0 +1,47 @@ ++/* ++ * This file contains the flask_op hypercall commands and definitions. ++ * ++ * Author: George Coker, ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2, ++ * as published by the Free Software Foundation. ++ */ ++ ++#ifndef __FLASK_OP_H__ ++#define __FLASK_OP_H__ ++ ++#define FLASK_LOAD 1 ++#define FLASK_GETENFORCE 2 ++#define FLASK_SETENFORCE 3 ++#define FLASK_CONTEXT_TO_SID 4 ++#define FLASK_SID_TO_CONTEXT 5 ++#define FLASK_ACCESS 6 ++#define FLASK_CREATE 7 ++#define FLASK_RELABEL 8 ++#define FLASK_USER 9 ++#define FLASK_POLICYVERS 10 ++#define FLASK_GETBOOL 11 ++#define FLASK_SETBOOL 12 ++#define FLASK_COMMITBOOLS 13 ++#define FLASK_MLS 14 ++#define FLASK_DISABLE 15 ++#define FLASK_GETAVC_THRESHOLD 16 ++#define FLASK_SETAVC_THRESHOLD 17 ++#define FLASK_AVC_HASHSTATS 18 ++#define FLASK_AVC_CACHESTATS 19 ++#define FLASK_MEMBER 20 ++#define FLASK_ADD_OCONTEXT 21 ++#define FLASK_DEL_OCONTEXT 22 ++ ++#define FLASK_LAST FLASK_DEL_OCONTEXT ++ ++typedef struct flask_op { ++ uint32_t cmd; ++ uint32_t size; ++ char *buf; ++} flask_op_t; ++ ++DEFINE_XEN_GUEST_HANDLE(flask_op_t); ++ ++#endif diff --git a/xen3-auto-xen-arch.diff b/xen3-auto-xen-arch.diff new file mode 100644 index 0000000..967793b --- /dev/null +++ b/xen3-auto-xen-arch.diff @@ -0,0 +1,45322 @@ +Subject: xen3 xen-arch +From: http://xenbits.xensource.com/linux-2.6.18-xen.hg (tip 1011:11175e60d393) +Patch-mainline: obsolete +Acked-by: jbeulich@novell.com + +List of files having Xen derivates (perhaps created during the merging +of newer kernel versions), for xen-port-patches.py to pick up (i.e. this +must be retained here until the XenSource tree has these in the right +places): ++++ linux/arch/x86/kernel/acpi/sleep-xen.c ++++ linux/arch/x86/kernel/apic/apic-xen.c ++++ linux/arch/x86/kernel/apic/io_apic-xen.c ++++ linux/arch/x86/kernel/apic/ipi-xen.c ++++ linux/arch/x86/kernel/apic/probe_32-xen.c ++++ linux/arch/x86/kernel/cpu/common_64-xen.c ++++ linux/arch/x86/kernel/e820-xen.c ++++ linux/arch/x86/kernel/head-xen.c ++++ linux/arch/x86/kernel/head32-xen.c ++++ linux/arch/x86/kernel/ioport-xen.c ++++ linux/arch/x86/kernel/io_apic-xen.c ++++ linux/arch/x86/kernel/ipi-xen.c ++++ linux/arch/x86/kernel/irq-xen.c ++++ linux/arch/x86/kernel/ldt-xen.c ++++ linux/arch/x86/kernel/microcode_core-xen.c ++++ linux/arch/x86/kernel/mpparse-xen.c ++++ linux/arch/x86/kernel/pci-nommu-xen.c ++++ linux/arch/x86/kernel/process-xen.c ++++ linux/arch/x86/kernel/setup-xen.c ++++ linux/arch/x86/kernel/smp-xen.c ++++ linux/arch/x86/kernel/traps-xen.c ++++ linux/arch/x86/kernel/x86_init-xen.c ++++ linux/arch/x86/mm/fault-xen.c ++++ linux/arch/x86/mm/init-xen.c ++++ linux/arch/x86/mm/iomap_32-xen.c ++++ linux/arch/x86/mm/ioremap-xen.c ++++ linux/arch/x86/mm/pageattr-xen.c ++++ linux/arch/x86/mm/pat-xen.c ++++ linux/arch/x86/mm/pgtable-xen.c ++++ linux/arch/x86/vdso/vdso32-setup-xen.c ++++ linux/drivers/char/mem-xen.c ++++ linux/arch/x86/include/mach-xen/asm/desc.h ++++ linux/arch/x86/include/mach-xen/asm/dma-mapping.h ++++ linux/arch/x86/include/mach-xen/asm/fixmap.h ++++ linux/arch/x86/include/mach-xen/asm/io.h ++++ linux/arch/x86/include/mach-xen/asm/ipi.h ++++ linux/arch/x86/include/mach-xen/asm/irq_vectors.h ++++ linux/arch/x86/include/mach-xen/asm/irqflags.h ++++ linux/arch/x86/include/mach-xen/asm/mmu_context.h ++++ linux/arch/x86/include/mach-xen/asm/pci.h ++++ linux/arch/x86/include/mach-xen/asm/pgalloc.h ++++ linux/arch/x86/include/mach-xen/asm/pgtable.h ++++ linux/arch/x86/include/mach-xen/asm/pgtable-3level_types.h ++++ linux/arch/x86/include/mach-xen/asm/pgtable_64_types.h ++++ linux/arch/x86/include/mach-xen/asm/pgtable_types.h ++++ linux/arch/x86/include/mach-xen/asm/processor.h ++++ linux/arch/x86/include/mach-xen/asm/smp.h ++++ linux/arch/x86/include/mach-xen/asm/spinlock.h ++++ linux/arch/x86/include/mach-xen/asm/spinlock_types.h ++++ linux/arch/x86/include/mach-xen/asm/swiotlb.h ++++ linux/arch/x86/include/mach-xen/asm/system.h ++++ linux/arch/x86/include/mach-xen/asm/tlbflush.h ++++ linux/arch/x86/include/mach-xen/asm/xor.h + +List of files folded into their native counterparts (and hence removed +from this patch for xen-port-patches.py to not needlessly pick them up; +for reference, prefixed with the version the removal occured): +2.6.18/arch/x86/include/mach-xen/asm/pgtable-2level.h +2.6.18/arch/x86/include/mach-xen/asm/pgtable-2level-defs.h +2.6.19/arch/x86/include/mach-xen/asm/ptrace.h +2.6.23/arch/x86/include/mach-xen/asm/ptrace_64.h +2.6.23/arch/x86/kernel/vsyscall-note_32-xen.S +2.6.24/arch/x86/include/mach-xen/asm/arch_hooks_64.h +2.6.24/arch/x86/include/mach-xen/asm/bootsetup_64.h +2.6.24/arch/x86/include/mach-xen/asm/mmu_32.h +2.6.24/arch/x86/include/mach-xen/asm/mmu_64.h +2.6.24/arch/x86/include/mach-xen/asm/nmi_64.h +2.6.24/arch/x86/include/mach-xen/asm/setup.h +2.6.24/arch/x86/include/mach-xen/asm/time_64.h (added in 2.6.20) +2.6.24/arch/x86/include/mach-xen/mach_timer.h +2.6.24/arch/x86/kernel/early_printk_32-xen.c +2.6.25/arch/x86/ia32/syscall32-xen.c +2.6.25/arch/x86/ia32/syscall32_syscall-xen.S +2.6.25/arch/x86/ia32/vsyscall-int80.S +2.6.25/arch/x86/include/mach-xen/asm/msr.h +2.6.25/arch/x86/include/mach-xen/asm/page_32.h +2.6.25/arch/x86/include/mach-xen/asm/spinlock_32.h +2.6.25/arch/x86/include/mach-xen/asm/timer.h (added in 2.6.24) +2.6.25/arch/x86/include/mach-xen/asm/timer_64.h +2.6.25/arch/x86/include/mach-xen/mach_time.h +2.6.25/arch/x86/kernel/acpi/boot-xen.c +2.6.26/arch/x86/include/mach-xen/asm/dma-mapping_32.h +2.6.26/arch/x86/include/mach-xen/asm/dma-mapping_64.h +2.6.26/arch/x86/include/mach-xen/asm/nmi.h (added in 2.6.24) +2.6.26/arch/x86/include/mach-xen/asm/scatterlist.h (added in 2.6.24) +2.6.26/arch/x86/include/mach-xen/asm/scatterlist_32.h +2.6.26/arch/x86/include/mach-xen/asm/swiotlb_32.h +2.6.26/arch/x86/kernel/pci-dma_32-xen.c +2.6.26/arch/x86/kernel/pci-swiotlb_64-xen.c +2.6.26/include/xen/xencomm.h +2.6.27/arch/x86/include/mach-xen/asm/e820.h (added in 2.6.24) +2.6.27/arch/x86/include/mach-xen/asm/e820_64.h +2.6.27/arch/x86/include/mach-xen/asm/hw_irq.h (added in 2.6.24) +2.6.27/arch/x86/include/mach-xen/asm/hw_irq_32.h +2.6.27/arch/x86/include/mach-xen/asm/hw_irq_64.h +2.6.27/arch/x86/include/mach-xen/asm/io_32.h +2.6.27/arch/x86/include/mach-xen/asm/io_64.h +2.6.27/arch/x86/include/mach-xen/asm/irq.h (added in 2.6.24) +2.6.27/arch/x86/include/mach-xen/asm/irq_64.h +2.6.27/arch/x86/kernel/e820_32-xen.c +2.6.28/arch/x86/include/mach-xen/asm/pci_64.h +2.6.28/arch/x86/include/mach-xen/asm/segment.h (added in 2.6.24) +2.6.28/arch/x86/include/mach-xen/asm/segment_32.h +2.6.30/arch/x86/include/mach-xen/asm/page.h (added in 2.6.24) +2.6.30/arch/x86/include/mach-xen/asm/page_64.h +2.6.30/arch/x86/include/mach-xen/asm/pci_32.h +2.6.30/arch/x86/kernel/apic/apic_xen_64.c +2.6.30/arch/x86/kernel/apic/probe_64-xen.c +2.6.30/arch/x86/kernel/setup_percpu-xen.c (added in 2.6.27) +2.6.31/arch/x86/kernel/init_task-xen.c +2.6.32/arch/x86/include/mach-xen/asm/setup_arch.h + +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/arch/x86/kernel/acpi/processor_extcntl_xen.c 2010-03-22 12:00:53.000000000 +0100 +@@ -0,0 +1,208 @@ ++/* ++ * processor_extcntl_xen.c - interface to notify Xen ++ * ++ * Copyright (C) 2008, Intel corporation ++ * ++ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or (at ++ * your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++static int xen_cx_notifier(struct acpi_processor *pr, int action) ++{ ++ int ret, count = 0, i; ++ xen_platform_op_t op = { ++ .cmd = XENPF_set_processor_pminfo, ++ .interface_version = XENPF_INTERFACE_VERSION, ++ .u.set_pminfo.id = pr->acpi_id, ++ .u.set_pminfo.type = XEN_PM_CX, ++ }; ++ struct xen_processor_cx *data, *buf; ++ struct acpi_processor_cx *cx; ++ ++ /* Convert to Xen defined structure and hypercall */ ++ buf = kzalloc(pr->power.count * sizeof(struct xen_processor_cx), ++ GFP_KERNEL); ++ if (!buf) ++ return -ENOMEM; ++ ++ data = buf; ++ for (i = 1; i <= pr->power.count; i++) { ++ cx = &pr->power.states[i]; ++ /* Skip invalid cstate entry */ ++ if (!cx->valid) ++ continue; ++ ++ data->type = cx->type; ++ data->latency = cx->latency; ++ data->power = cx->power; ++ data->reg.space_id = cx->reg.space_id; ++ data->reg.bit_width = cx->reg.bit_width; ++ data->reg.bit_offset = cx->reg.bit_offset; ++ data->reg.access_size = cx->reg.reserved; ++ data->reg.address = cx->reg.address; ++ ++ /* Get dependency relationships */ ++ if (cx->csd_count) { ++ printk("Wow! _CSD is found. Not support for now!\n"); ++ kfree(buf); ++ return -EINVAL; ++ } else { ++ data->dpcnt = 0; ++ set_xen_guest_handle(data->dp, NULL); ++ } ++ ++ data++; ++ count++; ++ } ++ ++ if (!count) { ++ printk("No available Cx info for cpu %d\n", pr->acpi_id); ++ kfree(buf); ++ return -EINVAL; ++ } ++ ++ op.u.set_pminfo.u.power.count = count; ++ op.u.set_pminfo.u.power.flags.bm_control = pr->flags.bm_control; ++ op.u.set_pminfo.u.power.flags.bm_check = pr->flags.bm_check; ++ op.u.set_pminfo.u.power.flags.has_cst = pr->flags.has_cst; ++ op.u.set_pminfo.u.power.flags.power_setup_done = pr->flags.power_setup_done; ++ ++ set_xen_guest_handle(op.u.set_pminfo.u.power.states, buf); ++ ret = HYPERVISOR_platform_op(&op); ++ kfree(buf); ++ return ret; ++} ++ ++static int xen_px_notifier(struct acpi_processor *pr, int action) ++{ ++ int ret = -EINVAL; ++ xen_platform_op_t op = { ++ .cmd = XENPF_set_processor_pminfo, ++ .interface_version = XENPF_INTERFACE_VERSION, ++ .u.set_pminfo.id = pr->acpi_id, ++ .u.set_pminfo.type = XEN_PM_PX, ++ }; ++ struct xen_processor_performance *perf; ++ struct xen_processor_px *states = NULL; ++ struct acpi_processor_performance *px; ++ struct acpi_psd_package *pdomain; ++ ++ if (!pr) ++ return -EINVAL; ++ ++ perf = &op.u.set_pminfo.u.perf; ++ px = pr->performance; ++ if (!px) ++ return -EINVAL; ++ ++ switch(action) { ++ case PROCESSOR_PM_CHANGE: ++ /* ppc dynamic handle */ ++ perf->flags = XEN_PX_PPC; ++ perf->platform_limit = pr->performance_platform_limit; ++ ++ ret = HYPERVISOR_platform_op(&op); ++ break; ++ ++ case PROCESSOR_PM_INIT: ++ /* px normal init */ ++ perf->flags = XEN_PX_PPC | ++ XEN_PX_PCT | ++ XEN_PX_PSS | ++ XEN_PX_PSD; ++ ++ /* ppc */ ++ perf->platform_limit = pr->performance_platform_limit; ++ ++ /* pct */ ++ xen_convert_pct_reg(&perf->control_register, &px->control_register); ++ xen_convert_pct_reg(&perf->status_register, &px->status_register); ++ ++ /* pss */ ++ perf->state_count = px->state_count; ++ states = kzalloc(px->state_count*sizeof(xen_processor_px_t),GFP_KERNEL); ++ if (!states) ++ return -ENOMEM; ++ xen_convert_pss_states(states, px->states, px->state_count); ++ set_xen_guest_handle(perf->states, states); ++ ++ /* psd */ ++ pdomain = &px->domain_info; ++ xen_convert_psd_pack(&perf->domain_info, pdomain); ++ if (pdomain->coord_type == DOMAIN_COORD_TYPE_SW_ALL) ++ perf->shared_type = CPUFREQ_SHARED_TYPE_ALL; ++ else if (pdomain->coord_type == DOMAIN_COORD_TYPE_SW_ANY) ++ perf->shared_type = CPUFREQ_SHARED_TYPE_ANY; ++ else if (pdomain->coord_type == DOMAIN_COORD_TYPE_HW_ALL) ++ perf->shared_type = CPUFREQ_SHARED_TYPE_HW; ++ else { ++ ret = -ENODEV; ++ kfree(states); ++ break; ++ } ++ ++ ret = HYPERVISOR_platform_op(&op); ++ kfree(states); ++ break; ++ ++ default: ++ break; ++ } ++ ++ return ret; ++} ++ ++static int xen_tx_notifier(struct acpi_processor *pr, int action) ++{ ++ return -EINVAL; ++} ++static int xen_hotplug_notifier(struct acpi_processor *pr, int event) ++{ ++ return -EINVAL; ++} ++ ++static struct processor_extcntl_ops xen_extcntl_ops = { ++ .hotplug = xen_hotplug_notifier, ++}; ++ ++void arch_acpi_processor_init_extcntl(const struct processor_extcntl_ops **ops) ++{ ++ unsigned int pmbits = (xen_start_info->flags & SIF_PM_MASK) >> 8; ++ ++ if (!pmbits) ++ return; ++ if (pmbits & XEN_PROCESSOR_PM_CX) ++ xen_extcntl_ops.pm_ops[PM_TYPE_IDLE] = xen_cx_notifier; ++ if (pmbits & XEN_PROCESSOR_PM_PX) ++ xen_extcntl_ops.pm_ops[PM_TYPE_PERF] = xen_px_notifier; ++ if (pmbits & XEN_PROCESSOR_PM_TX) ++ xen_extcntl_ops.pm_ops[PM_TYPE_THR] = xen_tx_notifier; ++ ++ *ops = &xen_extcntl_ops; ++} ++EXPORT_SYMBOL(arch_acpi_processor_init_extcntl); +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/arch/x86/kernel/acpi/sleep_32-xen.c 2008-04-15 09:29:41.000000000 +0200 +@@ -0,0 +1,113 @@ ++/* ++ * sleep.c - x86-specific ACPI sleep support. ++ * ++ * Copyright (C) 2001-2003 Patrick Mochel ++ * Copyright (C) 2001-2003 Pavel Machek ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++ ++#ifndef CONFIG_ACPI_PV_SLEEP ++/* address in low memory of the wakeup routine. */ ++unsigned long acpi_wakeup_address = 0; ++unsigned long acpi_video_flags; ++extern char wakeup_start, wakeup_end; ++ ++extern unsigned long FASTCALL(acpi_copy_wakeup_routine(unsigned long)); ++#endif ++ ++/** ++ * acpi_save_state_mem - save kernel state ++ * ++ * Create an identity mapped page table and copy the wakeup routine to ++ * low memory. ++ */ ++int acpi_save_state_mem(void) ++{ ++#ifndef CONFIG_ACPI_PV_SLEEP ++ if (!acpi_wakeup_address) ++ return 1; ++ memcpy((void *)acpi_wakeup_address, &wakeup_start, ++ &wakeup_end - &wakeup_start); ++ acpi_copy_wakeup_routine(acpi_wakeup_address); ++#endif ++ return 0; ++} ++ ++/* ++ * acpi_restore_state - undo effects of acpi_save_state_mem ++ */ ++void acpi_restore_state_mem(void) ++{ ++} ++ ++/** ++ * acpi_reserve_bootmem - do _very_ early ACPI initialisation ++ * ++ * We allocate a page from the first 1MB of memory for the wakeup ++ * routine for when we come back from a sleep state. The ++ * runtime allocator allows specification of <16MB pages, but not ++ * <1MB pages. ++ */ ++void __init acpi_reserve_bootmem(void) ++{ ++#ifndef CONFIG_ACPI_PV_SLEEP ++ if ((&wakeup_end - &wakeup_start) > PAGE_SIZE) { ++ printk(KERN_ERR ++ "ACPI: Wakeup code way too big, S3 disabled.\n"); ++ return; ++ } ++ ++ acpi_wakeup_address = (unsigned long)alloc_bootmem_low(PAGE_SIZE); ++ if (!acpi_wakeup_address) ++ printk(KERN_ERR "ACPI: Cannot allocate lowmem, S3 disabled.\n"); ++#endif ++} ++ ++#ifndef CONFIG_ACPI_PV_SLEEP ++static int __init acpi_sleep_setup(char *str) ++{ ++ while ((str != NULL) && (*str != '\0')) { ++ if (strncmp(str, "s3_bios", 7) == 0) ++ acpi_video_flags = 1; ++ if (strncmp(str, "s3_mode", 7) == 0) ++ acpi_video_flags |= 2; ++ str = strchr(str, ','); ++ if (str != NULL) ++ str += strspn(str, ", \t"); ++ } ++ return 1; ++} ++ ++__setup("acpi_sleep=", acpi_sleep_setup); ++ ++static __init int reset_videomode_after_s3(struct dmi_system_id *d) ++{ ++ acpi_video_flags |= 2; ++ return 0; ++} ++ ++static __initdata struct dmi_system_id acpisleep_dmi_table[] = { ++ { /* Reset video mode after returning from ACPI S3 sleep */ ++ .callback = reset_videomode_after_s3, ++ .ident = "Toshiba Satellite 4030cdt", ++ .matches = { ++ DMI_MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"), ++ }, ++ }, ++ {} ++}; ++ ++static int __init acpisleep_dmi_init(void) ++{ ++ dmi_check_system(acpisleep_dmi_table); ++ return 0; ++} ++ ++core_initcall(acpisleep_dmi_init); ++#endif /* CONFIG_ACPI_PV_SLEEP */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/arch/x86/kernel/apic_32-xen.c 2007-06-12 13:12:48.000000000 +0200 +@@ -0,0 +1,155 @@ ++/* ++ * Local APIC handling, local APIC timers ++ * ++ * (c) 1999, 2000 Ingo Molnar ++ * ++ * Fixes ++ * Maciej W. Rozycki : Bits for genuine 82489DX APICs; ++ * thanks to Eric Gilmore ++ * and Rolf G. Tews ++ * for testing these extensively. ++ * Maciej W. Rozycki : Various updates and fixes. ++ * Mikael Pettersson : Power Management for UP-APIC. ++ * Pavel Machek and ++ * Mikael Pettersson : PM converted to driver model. ++ */ ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "io_ports.h" ++ ++#ifndef CONFIG_XEN ++/* ++ * cpu_mask that denotes the CPUs that needs timer interrupt coming in as ++ * IPIs in place of local APIC timers ++ */ ++static cpumask_t timer_bcast_ipi; ++#endif ++ ++/* ++ * Knob to control our willingness to enable the local APIC. ++ */ ++int enable_local_apic __initdata = 0; /* -1=force-disable, +1=force-enable */ ++ ++/* ++ * Debug level ++ */ ++int apic_verbosity; ++ ++#ifndef CONFIG_XEN ++static int modern_apic(void) ++{ ++ unsigned int lvr, version; ++ /* AMD systems use old APIC versions, so check the CPU */ ++ if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD && ++ boot_cpu_data.x86 >= 0xf) ++ return 1; ++ lvr = apic_read(APIC_LVR); ++ version = GET_APIC_VERSION(lvr); ++ return version >= 0x14; ++} ++#endif /* !CONFIG_XEN */ ++ ++/* ++ * 'what should we do if we get a hw irq event on an illegal vector'. ++ * each architecture has to answer this themselves. ++ */ ++void ack_bad_irq(unsigned int irq) ++{ ++ printk("unexpected IRQ trap at vector %02x\n", irq); ++ /* ++ * Currently unexpected vectors happen only on SMP and APIC. ++ * We _must_ ack these because every local APIC has only N ++ * irq slots per priority level, and a 'hanging, unacked' IRQ ++ * holds up an irq slot - in excessive cases (when multiple ++ * unexpected vectors occur) that might lock up the APIC ++ * completely. ++ * But only ack when the APIC is enabled -AK ++ */ ++ if (cpu_has_apic) ++ ack_APIC_irq(); ++} ++ ++int get_physical_broadcast(void) ++{ ++ return 0xff; ++} ++ ++#ifndef CONFIG_XEN ++#ifndef CONFIG_SMP ++static void up_apic_timer_interrupt_call(struct pt_regs *regs) ++{ ++ int cpu = smp_processor_id(); ++ ++ /* ++ * the NMI deadlock-detector uses this. ++ */ ++ per_cpu(irq_stat, cpu).apic_timer_irqs++; ++ ++ smp_local_timer_interrupt(regs); ++} ++#endif ++ ++void smp_send_timer_broadcast_ipi(struct pt_regs *regs) ++{ ++ cpumask_t mask; ++ ++ cpus_and(mask, cpu_online_map, timer_bcast_ipi); ++ if (!cpus_empty(mask)) { ++#ifdef CONFIG_SMP ++ send_IPI_mask(mask, LOCAL_TIMER_VECTOR); ++#else ++ /* ++ * We can directly call the apic timer interrupt handler ++ * in UP case. Minus all irq related functions ++ */ ++ up_apic_timer_interrupt_call(regs); ++#endif ++ } ++} ++#endif ++ ++int setup_profiling_timer(unsigned int multiplier) ++{ ++ return -EINVAL; ++} ++ ++/* ++ * This initializes the IO-APIC and APIC hardware if this is ++ * a UP kernel. ++ */ ++int __init APIC_init_uniprocessor (void) ++{ ++#ifdef CONFIG_X86_IO_APIC ++ if (smp_found_config) ++ if (!skip_ioapic_setup && nr_ioapics) ++ setup_IO_APIC(); ++#endif ++ ++ return 0; ++} +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/arch/x86/kernel/cpu/common-xen.c 2009-05-19 09:16:41.000000000 +0200 +@@ -0,0 +1,745 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#ifdef CONFIG_X86_LOCAL_APIC ++#include ++#include ++#include ++#else ++#ifdef CONFIG_XEN ++#define phys_pkg_id(a,b) a ++#endif ++#endif ++#include ++ ++#include "cpu.h" ++ ++DEFINE_PER_CPU(struct Xgt_desc_struct, cpu_gdt_descr); ++EXPORT_PER_CPU_SYMBOL(cpu_gdt_descr); ++ ++#ifndef CONFIG_XEN ++DEFINE_PER_CPU(unsigned char, cpu_16bit_stack[CPU_16BIT_STACK_SIZE]); ++EXPORT_PER_CPU_SYMBOL(cpu_16bit_stack); ++#endif ++ ++static int cachesize_override __cpuinitdata = -1; ++static int disable_x86_fxsr __cpuinitdata; ++static int disable_x86_serial_nr __cpuinitdata = 1; ++static int disable_x86_sep __cpuinitdata; ++ ++struct cpu_dev * cpu_devs[X86_VENDOR_NUM] = {}; ++ ++extern int disable_pse; ++ ++static void default_init(struct cpuinfo_x86 * c) ++{ ++ /* Not much we can do here... */ ++ /* Check if at least it has cpuid */ ++ if (c->cpuid_level == -1) { ++ /* No cpuid. It must be an ancient CPU */ ++ if (c->x86 == 4) ++ strcpy(c->x86_model_id, "486"); ++ else if (c->x86 == 3) ++ strcpy(c->x86_model_id, "386"); ++ } ++} ++ ++static struct cpu_dev default_cpu = { ++ .c_init = default_init, ++ .c_vendor = "Unknown", ++}; ++static struct cpu_dev * this_cpu = &default_cpu; ++ ++static int __init cachesize_setup(char *str) ++{ ++ get_option (&str, &cachesize_override); ++ return 1; ++} ++__setup("cachesize=", cachesize_setup); ++ ++int __cpuinit get_model_name(struct cpuinfo_x86 *c) ++{ ++ unsigned int *v; ++ char *p, *q; ++ ++ if (cpuid_eax(0x80000000) < 0x80000004) ++ return 0; ++ ++ v = (unsigned int *) c->x86_model_id; ++ cpuid(0x80000002, &v[0], &v[1], &v[2], &v[3]); ++ cpuid(0x80000003, &v[4], &v[5], &v[6], &v[7]); ++ cpuid(0x80000004, &v[8], &v[9], &v[10], &v[11]); ++ c->x86_model_id[48] = 0; ++ ++ /* Intel chips right-justify this string for some dumb reason; ++ undo that brain damage */ ++ p = q = &c->x86_model_id[0]; ++ while ( *p == ' ' ) ++ p++; ++ if ( p != q ) { ++ while ( *p ) ++ *q++ = *p++; ++ while ( q <= &c->x86_model_id[48] ) ++ *q++ = '\0'; /* Zero-pad the rest */ ++ } ++ ++ return 1; ++} ++ ++ ++void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c) ++{ ++ unsigned int n, dummy, ecx, edx, l2size; ++ ++ n = cpuid_eax(0x80000000); ++ ++ if (n >= 0x80000005) { ++ cpuid(0x80000005, &dummy, &dummy, &ecx, &edx); ++ printk(KERN_INFO "CPU: L1 I Cache: %dK (%d bytes/line), D cache %dK (%d bytes/line)\n", ++ edx>>24, edx&0xFF, ecx>>24, ecx&0xFF); ++ c->x86_cache_size=(ecx>>24)+(edx>>24); ++ } ++ ++ if (n < 0x80000006) /* Some chips just has a large L1. */ ++ return; ++ ++ ecx = cpuid_ecx(0x80000006); ++ l2size = ecx >> 16; ++ ++ /* do processor-specific cache resizing */ ++ if (this_cpu->c_size_cache) ++ l2size = this_cpu->c_size_cache(c,l2size); ++ ++ /* Allow user to override all this if necessary. */ ++ if (cachesize_override != -1) ++ l2size = cachesize_override; ++ ++ if ( l2size == 0 ) ++ return; /* Again, no L2 cache is possible */ ++ ++ c->x86_cache_size = l2size; ++ ++ printk(KERN_INFO "CPU: L2 Cache: %dK (%d bytes/line)\n", ++ l2size, ecx & 0xFF); ++} ++ ++/* Naming convention should be: [()] */ ++/* This table only is used unless init_() below doesn't set it; */ ++/* in particular, if CPUID levels 0x80000002..4 are supported, this isn't used */ ++ ++/* Look up CPU names by table lookup. */ ++static char __cpuinit *table_lookup_model(struct cpuinfo_x86 *c) ++{ ++ struct cpu_model_info *info; ++ ++ if ( c->x86_model >= 16 ) ++ return NULL; /* Range check */ ++ ++ if (!this_cpu) ++ return NULL; ++ ++ info = this_cpu->c_models; ++ ++ while (info && info->family) { ++ if (info->family == c->x86) ++ return info->model_names[c->x86_model]; ++ info++; ++ } ++ return NULL; /* Not found */ ++} ++ ++ ++static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c, int early) ++{ ++ char *v = c->x86_vendor_id; ++ int i; ++ static int printed; ++ ++ for (i = 0; i < X86_VENDOR_NUM; i++) { ++ if (cpu_devs[i]) { ++ if (!strcmp(v,cpu_devs[i]->c_ident[0]) || ++ (cpu_devs[i]->c_ident[1] && ++ !strcmp(v,cpu_devs[i]->c_ident[1]))) { ++ c->x86_vendor = i; ++ if (!early) ++ this_cpu = cpu_devs[i]; ++ return; ++ } ++ } ++ } ++ if (!printed) { ++ printed++; ++ printk(KERN_ERR "CPU: Vendor unknown, using generic init.\n"); ++ printk(KERN_ERR "CPU: Your system may be unstable.\n"); ++ } ++ c->x86_vendor = X86_VENDOR_UNKNOWN; ++ this_cpu = &default_cpu; ++} ++ ++ ++static int __init x86_fxsr_setup(char * s) ++{ ++ disable_x86_fxsr = 1; ++ return 1; ++} ++__setup("nofxsr", x86_fxsr_setup); ++ ++ ++static int __init x86_sep_setup(char * s) ++{ ++ disable_x86_sep = 1; ++ return 1; ++} ++__setup("nosep", x86_sep_setup); ++ ++ ++/* Standard macro to see if a specific flag is changeable */ ++static inline int flag_is_changeable_p(u32 flag) ++{ ++ u32 f1, f2; ++ ++ asm("pushfl\n\t" ++ "pushfl\n\t" ++ "popl %0\n\t" ++ "movl %0,%1\n\t" ++ "xorl %2,%0\n\t" ++ "pushl %0\n\t" ++ "popfl\n\t" ++ "pushfl\n\t" ++ "popl %0\n\t" ++ "popfl\n\t" ++ : "=&r" (f1), "=&r" (f2) ++ : "ir" (flag)); ++ ++ return ((f1^f2) & flag) != 0; ++} ++ ++ ++/* Probe for the CPUID instruction */ ++static int __cpuinit have_cpuid_p(void) ++{ ++ return flag_is_changeable_p(X86_EFLAGS_ID); ++} ++ ++/* Do minimum CPU detection early. ++ Fields really needed: vendor, cpuid_level, family, model, mask, cache alignment. ++ The others are not touched to avoid unwanted side effects. ++ ++ WARNING: this function is only called on the BP. Don't add code here ++ that is supposed to run on all CPUs. */ ++static void __init early_cpu_detect(void) ++{ ++ struct cpuinfo_x86 *c = &boot_cpu_data; ++ ++ c->x86_cache_alignment = 32; ++ ++ if (!have_cpuid_p()) ++ return; ++ ++ /* Get vendor name */ ++ cpuid(0x00000000, &c->cpuid_level, ++ (int *)&c->x86_vendor_id[0], ++ (int *)&c->x86_vendor_id[8], ++ (int *)&c->x86_vendor_id[4]); ++ ++ get_cpu_vendor(c, 1); ++ ++ c->x86 = 4; ++ if (c->cpuid_level >= 0x00000001) { ++ u32 junk, tfms, cap0, misc; ++ cpuid(0x00000001, &tfms, &misc, &junk, &cap0); ++ c->x86 = (tfms >> 8) & 15; ++ c->x86_model = (tfms >> 4) & 15; ++ if (c->x86 == 0xf) ++ c->x86 += (tfms >> 20) & 0xff; ++ if (c->x86 >= 0x6) ++ c->x86_model += ((tfms >> 16) & 0xF) << 4; ++ c->x86_mask = tfms & 15; ++ if (cap0 & (1<<19)) ++ c->x86_cache_alignment = ((misc >> 8) & 0xff) * 8; ++ } ++} ++ ++void __cpuinit generic_identify(struct cpuinfo_x86 * c) ++{ ++ u32 tfms, xlvl; ++ int ebx; ++ ++ if (have_cpuid_p()) { ++ /* Get vendor name */ ++ cpuid(0x00000000, &c->cpuid_level, ++ (int *)&c->x86_vendor_id[0], ++ (int *)&c->x86_vendor_id[8], ++ (int *)&c->x86_vendor_id[4]); ++ ++ get_cpu_vendor(c, 0); ++ /* Initialize the standard set of capabilities */ ++ /* Note that the vendor-specific code below might override */ ++ ++ /* Intel-defined flags: level 0x00000001 */ ++ if ( c->cpuid_level >= 0x00000001 ) { ++ u32 capability, excap; ++ cpuid(0x00000001, &tfms, &ebx, &excap, &capability); ++ c->x86_capability[0] = capability; ++ c->x86_capability[4] = excap; ++ c->x86 = (tfms >> 8) & 15; ++ c->x86_model = (tfms >> 4) & 15; ++ if (c->x86 == 0xf) ++ c->x86 += (tfms >> 20) & 0xff; ++ if (c->x86 >= 0x6) ++ c->x86_model += ((tfms >> 16) & 0xF) << 4; ++ c->x86_mask = tfms & 15; ++#ifndef CONFIG_XEN ++#ifdef CONFIG_X86_HT ++ c->apicid = phys_pkg_id((ebx >> 24) & 0xFF, 0); ++#else ++ c->apicid = (ebx >> 24) & 0xFF; ++#endif ++#endif ++ } else { ++ /* Have CPUID level 0 only - unheard of */ ++ c->x86 = 4; ++ } ++ ++ /* AMD-defined flags: level 0x80000001 */ ++ xlvl = cpuid_eax(0x80000000); ++ if ( (xlvl & 0xffff0000) == 0x80000000 ) { ++ if ( xlvl >= 0x80000001 ) { ++ c->x86_capability[1] = cpuid_edx(0x80000001); ++ c->x86_capability[6] = cpuid_ecx(0x80000001); ++ } ++ if ( xlvl >= 0x80000004 ) ++ get_model_name(c); /* Default name */ ++ } ++ } ++ ++ early_intel_workaround(c); ++ ++#ifdef CONFIG_X86_HT ++ c->phys_proc_id = (cpuid_ebx(1) >> 24) & 0xff; ++#endif ++} ++ ++static void __cpuinit squash_the_stupid_serial_number(struct cpuinfo_x86 *c) ++{ ++ if (cpu_has(c, X86_FEATURE_PN) && disable_x86_serial_nr ) { ++ /* Disable processor serial number */ ++ unsigned long lo,hi; ++ rdmsr(MSR_IA32_BBL_CR_CTL,lo,hi); ++ lo |= 0x200000; ++ wrmsr(MSR_IA32_BBL_CR_CTL,lo,hi); ++ printk(KERN_NOTICE "CPU serial number disabled.\n"); ++ clear_bit(X86_FEATURE_PN, c->x86_capability); ++ ++ /* Disabling the serial number may affect the cpuid level */ ++ c->cpuid_level = cpuid_eax(0); ++ } ++} ++ ++static int __init x86_serial_nr_setup(char *s) ++{ ++ disable_x86_serial_nr = 0; ++ return 1; ++} ++__setup("serialnumber", x86_serial_nr_setup); ++ ++ ++ ++/* ++ * This does the hard work of actually picking apart the CPU stuff... ++ */ ++void __cpuinit identify_cpu(struct cpuinfo_x86 *c) ++{ ++ int i; ++ ++ c->loops_per_jiffy = loops_per_jiffy; ++ c->x86_cache_size = -1; ++ c->x86_vendor = X86_VENDOR_UNKNOWN; ++ c->cpuid_level = -1; /* CPUID not detected */ ++ c->x86_model = c->x86_mask = 0; /* So far unknown... */ ++ c->x86_vendor_id[0] = '\0'; /* Unset */ ++ c->x86_model_id[0] = '\0'; /* Unset */ ++ c->x86_max_cores = 1; ++ memset(&c->x86_capability, 0, sizeof c->x86_capability); ++ ++ if (!have_cpuid_p()) { ++ /* First of all, decide if this is a 486 or higher */ ++ /* It's a 486 if we can modify the AC flag */ ++ if ( flag_is_changeable_p(X86_EFLAGS_AC) ) ++ c->x86 = 4; ++ else ++ c->x86 = 3; ++ } ++ ++ generic_identify(c); ++ ++ printk(KERN_DEBUG "CPU: After generic identify, caps:"); ++ for (i = 0; i < NCAPINTS; i++) ++ printk(" %08lx", c->x86_capability[i]); ++ printk("\n"); ++ ++ if (this_cpu->c_identify) { ++ this_cpu->c_identify(c); ++ ++ printk(KERN_DEBUG "CPU: After vendor identify, caps:"); ++ for (i = 0; i < NCAPINTS; i++) ++ printk(" %08lx", c->x86_capability[i]); ++ printk("\n"); ++ } ++ ++ /* ++ * Vendor-specific initialization. In this section we ++ * canonicalize the feature flags, meaning if there are ++ * features a certain CPU supports which CPUID doesn't ++ * tell us, CPUID claiming incorrect flags, or other bugs, ++ * we handle them here. ++ * ++ * At the end of this section, c->x86_capability better ++ * indicate the features this CPU genuinely supports! ++ */ ++ if (this_cpu->c_init) ++ this_cpu->c_init(c); ++ ++ /* Disable the PN if appropriate */ ++ squash_the_stupid_serial_number(c); ++ ++ /* ++ * The vendor-specific functions might have changed features. Now ++ * we do "generic changes." ++ */ ++ ++ /* TSC disabled? */ ++ if ( tsc_disable ) ++ clear_bit(X86_FEATURE_TSC, c->x86_capability); ++ ++ /* FXSR disabled? */ ++ if (disable_x86_fxsr) { ++ clear_bit(X86_FEATURE_FXSR, c->x86_capability); ++ clear_bit(X86_FEATURE_XMM, c->x86_capability); ++ } ++ ++ /* SEP disabled? */ ++ if (disable_x86_sep) ++ clear_bit(X86_FEATURE_SEP, c->x86_capability); ++ ++ if (disable_pse) ++ clear_bit(X86_FEATURE_PSE, c->x86_capability); ++ ++ /* If the model name is still unset, do table lookup. */ ++ if ( !c->x86_model_id[0] ) { ++ char *p; ++ p = table_lookup_model(c); ++ if ( p ) ++ strcpy(c->x86_model_id, p); ++ else ++ /* Last resort... */ ++ sprintf(c->x86_model_id, "%02x/%02x", ++ c->x86, c->x86_model); ++ } ++ ++ /* Now the feature flags better reflect actual CPU features! */ ++ ++ printk(KERN_DEBUG "CPU: After all inits, caps:"); ++ for (i = 0; i < NCAPINTS; i++) ++ printk(" %08lx", c->x86_capability[i]); ++ printk("\n"); ++ ++ /* ++ * On SMP, boot_cpu_data holds the common feature set between ++ * all CPUs; so make sure that we indicate which features are ++ * common between the CPUs. The first time this routine gets ++ * executed, c == &boot_cpu_data. ++ */ ++ if ( c != &boot_cpu_data ) { ++ /* AND the already accumulated flags with these */ ++ for ( i = 0 ; i < NCAPINTS ; i++ ) ++ boot_cpu_data.x86_capability[i] &= c->x86_capability[i]; ++ } ++ ++ /* Init Machine Check Exception if available. */ ++ mcheck_init(c); ++ ++ if (c == &boot_cpu_data) ++ sysenter_setup(); ++ enable_sep_cpu(); ++ ++ if (c == &boot_cpu_data) ++ mtrr_bp_init(); ++ else ++ mtrr_ap_init(); ++} ++ ++#ifdef CONFIG_X86_HT ++void __cpuinit detect_ht(struct cpuinfo_x86 *c) ++{ ++ u32 eax, ebx, ecx, edx; ++ int index_msb, core_bits; ++ ++ cpuid(1, &eax, &ebx, &ecx, &edx); ++ ++ if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY)) ++ return; ++ ++ smp_num_siblings = (ebx & 0xff0000) >> 16; ++ ++ if (smp_num_siblings == 1) { ++ printk(KERN_INFO "CPU: Hyper-Threading is disabled\n"); ++ } else if (smp_num_siblings > 1 ) { ++ ++ if (smp_num_siblings > NR_CPUS) { ++ printk(KERN_WARNING "CPU: Unsupported number of the " ++ "siblings %d", smp_num_siblings); ++ smp_num_siblings = 1; ++ return; ++ } ++ ++ index_msb = get_count_order(smp_num_siblings); ++ c->phys_proc_id = phys_pkg_id((ebx >> 24) & 0xFF, index_msb); ++ ++ printk(KERN_INFO "CPU: Physical Processor ID: %d\n", ++ c->phys_proc_id); ++ ++ smp_num_siblings = smp_num_siblings / c->x86_max_cores; ++ ++ index_msb = get_count_order(smp_num_siblings) ; ++ ++ core_bits = get_count_order(c->x86_max_cores); ++ ++ c->cpu_core_id = phys_pkg_id((ebx >> 24) & 0xFF, index_msb) & ++ ((1 << core_bits) - 1); ++ ++ if (c->x86_max_cores > 1) ++ printk(KERN_INFO "CPU: Processor Core ID: %d\n", ++ c->cpu_core_id); ++ } ++} ++#endif ++ ++void __cpuinit print_cpu_info(struct cpuinfo_x86 *c) ++{ ++ char *vendor = NULL; ++ ++ if (c->x86_vendor < X86_VENDOR_NUM) ++ vendor = this_cpu->c_vendor; ++ else if (c->cpuid_level >= 0) ++ vendor = c->x86_vendor_id; ++ ++ if (vendor && strncmp(c->x86_model_id, vendor, strlen(vendor))) ++ printk("%s ", vendor); ++ ++ if (!c->x86_model_id[0]) ++ printk("%d86", c->x86); ++ else ++ printk("%s", c->x86_model_id); ++ ++ if (c->x86_mask || c->cpuid_level >= 0) ++ printk(" stepping %02x\n", c->x86_mask); ++ else ++ printk("\n"); ++} ++ ++cpumask_t cpu_initialized __cpuinitdata = CPU_MASK_NONE; ++ ++/* This is hacky. :) ++ * We're emulating future behavior. ++ * In the future, the cpu-specific init functions will be called implicitly ++ * via the magic of initcalls. ++ * They will insert themselves into the cpu_devs structure. ++ * Then, when cpu_init() is called, we can just iterate over that array. ++ */ ++ ++extern int intel_cpu_init(void); ++extern int cyrix_init_cpu(void); ++extern int nsc_init_cpu(void); ++extern int amd_init_cpu(void); ++extern int centaur_init_cpu(void); ++extern int transmeta_init_cpu(void); ++extern int rise_init_cpu(void); ++extern int nexgen_init_cpu(void); ++extern int umc_init_cpu(void); ++ ++void __init early_cpu_init(void) ++{ ++ intel_cpu_init(); ++ cyrix_init_cpu(); ++ nsc_init_cpu(); ++ amd_init_cpu(); ++ centaur_init_cpu(); ++ transmeta_init_cpu(); ++ rise_init_cpu(); ++ nexgen_init_cpu(); ++ umc_init_cpu(); ++ early_cpu_detect(); ++ ++#ifdef CONFIG_DEBUG_PAGEALLOC ++ /* pse is not compatible with on-the-fly unmapping, ++ * disable it even if the cpus claim to support it. ++ */ ++ clear_bit(X86_FEATURE_PSE, boot_cpu_data.x86_capability); ++ disable_pse = 1; ++#endif ++} ++ ++static void __cpuinit cpu_gdt_init(const struct Xgt_desc_struct *gdt_descr) ++{ ++ unsigned long frames[16]; ++ unsigned long va; ++ int f; ++ ++ for (va = gdt_descr->address, f = 0; ++ va < gdt_descr->address + gdt_descr->size; ++ va += PAGE_SIZE, f++) { ++ frames[f] = virt_to_mfn(va); ++ make_lowmem_page_readonly( ++ (void *)va, XENFEAT_writable_descriptor_tables); ++ } ++ if (HYPERVISOR_set_gdt(frames, (gdt_descr->size + 1) / 8)) ++ BUG(); ++} ++ ++/* ++ * cpu_init() initializes state that is per-CPU. Some data is already ++ * initialized (naturally) in the bootstrap process, such as the GDT ++ * and IDT. We reload them nevertheless, this function acts as a ++ * 'CPU state barrier', nothing should get across. ++ */ ++void __cpuinit cpu_init(void) ++{ ++ int cpu = smp_processor_id(); ++#ifndef CONFIG_X86_NO_TSS ++ struct tss_struct * t = &per_cpu(init_tss, cpu); ++#endif ++ struct thread_struct *thread = ¤t->thread; ++ struct desc_struct *gdt; ++ struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, cpu); ++ ++ if (cpu_test_and_set(cpu, cpu_initialized)) { ++ printk(KERN_WARNING "CPU#%d already initialized!\n", cpu); ++ for (;;) local_irq_enable(); ++ } ++ printk(KERN_INFO "Initializing CPU#%d\n", cpu); ++ ++ if (cpu_has_vme || cpu_has_de) ++ clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE); ++ if (tsc_disable && cpu_has_tsc) { ++ printk(KERN_NOTICE "Disabling TSC...\n"); ++ /**** FIX-HPA: DOES THIS REALLY BELONG HERE? ****/ ++ clear_bit(X86_FEATURE_TSC, boot_cpu_data.x86_capability); ++ set_in_cr4(X86_CR4_TSD); ++ } ++ ++#ifndef CONFIG_XEN ++ /* The CPU hotplug case */ ++ if (cpu_gdt_descr->address) { ++ gdt = (struct desc_struct *)cpu_gdt_descr->address; ++ memset(gdt, 0, PAGE_SIZE); ++ goto old_gdt; ++ } ++ /* ++ * This is a horrible hack to allocate the GDT. The problem ++ * is that cpu_init() is called really early for the boot CPU ++ * (and hence needs bootmem) but much later for the secondary ++ * CPUs, when bootmem will have gone away ++ */ ++ if (NODE_DATA(0)->bdata->node_bootmem_map) { ++ gdt = (struct desc_struct *)alloc_bootmem_pages(PAGE_SIZE); ++ /* alloc_bootmem_pages panics on failure, so no check */ ++ memset(gdt, 0, PAGE_SIZE); ++ } else { ++ gdt = (struct desc_struct *)get_zeroed_page(GFP_KERNEL); ++ if (unlikely(!gdt)) { ++ printk(KERN_CRIT "CPU%d failed to allocate GDT\n", cpu); ++ for (;;) ++ local_irq_enable(); ++ } ++ } ++old_gdt: ++ /* ++ * Initialize the per-CPU GDT with the boot GDT, ++ * and set up the GDT descriptor: ++ */ ++ memcpy(gdt, cpu_gdt_table, GDT_SIZE); ++ ++ /* Set up GDT entry for 16bit stack */ ++ *(__u64 *)(&gdt[GDT_ENTRY_ESPFIX_SS]) |= ++ ((((__u64)stk16_off) << 16) & 0x000000ffffff0000ULL) | ++ ((((__u64)stk16_off) << 32) & 0xff00000000000000ULL) | ++ (CPU_16BIT_STACK_SIZE - 1); ++ ++ cpu_gdt_descr->size = GDT_SIZE - 1; ++ cpu_gdt_descr->address = (unsigned long)gdt; ++#else ++ if (cpu == 0 && cpu_gdt_descr->address == 0) { ++ gdt = (struct desc_struct *)alloc_bootmem_pages(PAGE_SIZE); ++ /* alloc_bootmem_pages panics on failure, so no check */ ++ memset(gdt, 0, PAGE_SIZE); ++ ++ memcpy(gdt, cpu_gdt_table, GDT_SIZE); ++ ++ cpu_gdt_descr->size = GDT_SIZE; ++ cpu_gdt_descr->address = (unsigned long)gdt; ++ } ++#endif ++ ++ cpu_gdt_init(cpu_gdt_descr); ++ ++ /* ++ * Set up and load the per-CPU TSS and LDT ++ */ ++ atomic_inc(&init_mm.mm_count); ++ current->active_mm = &init_mm; ++ if (current->mm) ++ BUG(); ++ enter_lazy_tlb(&init_mm, current); ++ ++ load_esp0(t, thread); ++ ++ load_LDT(&init_mm.context); ++ ++#ifdef CONFIG_DOUBLEFAULT ++ /* Set up doublefault TSS pointer in the GDT */ ++ __set_tss_desc(cpu, GDT_ENTRY_DOUBLEFAULT_TSS, &doublefault_tss); ++#endif ++ ++ /* Clear %fs and %gs. */ ++ asm volatile ("xorl %eax, %eax; movl %eax, %fs; movl %eax, %gs"); ++ ++ /* Clear all 6 debug registers: */ ++ set_debugreg(0, 0); ++ set_debugreg(0, 1); ++ set_debugreg(0, 2); ++ set_debugreg(0, 3); ++ set_debugreg(0, 6); ++ set_debugreg(0, 7); ++ ++ /* ++ * Force FPU initialization: ++ */ ++ current_thread_info()->status = 0; ++ clear_used_math(); ++ mxcsr_feature_mask_init(); ++} ++ ++#ifdef CONFIG_HOTPLUG_CPU ++void __cpuinit cpu_uninit(void) ++{ ++ int cpu = raw_smp_processor_id(); ++ cpu_clear(cpu, cpu_initialized); ++ ++ /* lazy TLB state */ ++ per_cpu(cpu_tlbstate, cpu).state = 0; ++ per_cpu(cpu_tlbstate, cpu).active_mm = &init_mm; ++} ++#endif +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/arch/x86/kernel/cpu/mcheck/mce_dom0.c 2009-10-01 11:00:47.000000000 +0200 +@@ -0,0 +1,134 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static int convert_log(struct mc_info *mi) ++{ ++ struct mcinfo_common *mic = NULL; ++ struct mcinfo_global *mc_global; ++ struct mcinfo_bank *mc_bank; ++ struct mce m; ++ ++ x86_mcinfo_lookup(mic, mi, MC_TYPE_GLOBAL); ++ if (mic == NULL) ++ { ++ printk(KERN_ERR "DOM0_MCE_LOG: global data is NULL\n"); ++ return -1; ++ } ++ ++ mc_global = (struct mcinfo_global*)mic; ++ m.mcgstatus = mc_global->mc_gstatus; ++ m.cpu = mc_global->mc_coreid;/*for test*/ ++ x86_mcinfo_lookup(mic, mi, MC_TYPE_BANK); ++ do ++ { ++ if (mic == NULL || mic->size == 0) ++ break; ++ if (mic->type == MC_TYPE_BANK) ++ { ++ mc_bank = (struct mcinfo_bank*)mic; ++ m.misc = mc_bank->mc_misc; ++ m.status = mc_bank->mc_status; ++ m.addr = mc_bank->mc_addr; ++ m.tsc = mc_bank->mc_tsc; ++ m.res1 = mc_bank->mc_ctrl2; ++ m.bank = mc_bank->mc_bank; ++ printk(KERN_DEBUG "[CPU%d, BANK%d, addr %llx, state %llx]\n", ++ m.bank, m.cpu, m.addr, m.status); ++ /*log this record*/ ++ mce_log(&m); ++ } ++ mic = x86_mcinfo_next(mic); ++ }while (1); ++ ++ return 0; ++} ++ ++static struct mc_info *g_mi; ++ ++/*dom0 mce virq handler, logging physical mce error info*/ ++ ++static irqreturn_t mce_dom0_interrupt(int irq, void *dev_id, ++ struct pt_regs *regs) ++{ ++ xen_mc_t mc_op; ++ int result = 0; ++ ++ printk(KERN_DEBUG "MCE_DOM0_LOG: enter dom0 mce vIRQ handler\n"); ++ mc_op.cmd = XEN_MC_fetch; ++ mc_op.interface_version = XEN_MCA_INTERFACE_VERSION; ++ set_xen_guest_handle(mc_op.u.mc_fetch.data, g_mi); ++urgent: ++ mc_op.u.mc_fetch.flags = XEN_MC_URGENT; ++ result = HYPERVISOR_mca(&mc_op); ++ if (result || mc_op.u.mc_fetch.flags & XEN_MC_NODATA || ++ mc_op.u.mc_fetch.flags & XEN_MC_FETCHFAILED) ++ { ++ printk(KERN_DEBUG "MCE_DOM0_LOG: No more urgent data\n"); ++ goto nonurgent; ++ } ++ else ++ { ++ result = convert_log(g_mi); ++ if (result) { ++ printk(KERN_ERR "MCE_DOM0_LOG: Log conversion failed\n"); ++ goto end; ++ } ++ /* After fetching the telem from DOM0, we need to dec the telem's ++ * refcnt and release the entry. The telem is reserved and inc ++ * refcnt when filling the telem. ++ */ ++ mc_op.u.mc_fetch.flags = XEN_MC_URGENT | XEN_MC_ACK; ++ result = HYPERVISOR_mca(&mc_op); ++ ++ goto urgent; ++ } ++nonurgent: ++ mc_op.u.mc_fetch.flags = XEN_MC_NONURGENT; ++ result = HYPERVISOR_mca(&mc_op); ++ if (result || mc_op.u.mc_fetch.flags & XEN_MC_NODATA || ++ mc_op.u.mc_fetch.flags & XEN_MC_FETCHFAILED) ++ { ++ printk(KERN_DEBUG "MCE_DOM0_LOG: No more nonurgent data\n"); ++ goto end; ++ } ++ else ++ { ++ result = convert_log(g_mi); ++ if (result) { ++ printk(KERN_ERR "MCE_DOM0_LOG: Log conversion failed\n"); ++ goto end; ++ } ++ /* After fetching the telem from DOM0, we need to dec the telem's ++ * refcnt and release the entry. The telem is reserved and inc ++ * refcnt when filling the telem. ++ */ ++ mc_op.u.mc_fetch.flags = XEN_MC_NONURGENT | XEN_MC_ACK; ++ result = HYPERVISOR_mca(&mc_op); ++ ++ goto nonurgent; ++ } ++end: ++ return IRQ_HANDLED; ++} ++ ++void bind_virq_for_mce(void) ++{ ++ int ret; ++ ++ ret = bind_virq_to_irqhandler(VIRQ_MCA, 0, ++ mce_dom0_interrupt, 0, "mce", NULL); ++ ++ g_mi = kmalloc(sizeof(struct mc_info), GFP_KERNEL); ++ if (ret < 0) ++ printk(KERN_ERR "MCE_DOM0_LOG: bind_virq for DOM0 failed\n"); ++ ++ /* Log the machine checks left over from the previous reset. */ ++ mce_dom0_interrupt(VIRQ_MCA, NULL, NULL); ++} ++ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/arch/x86/kernel/cpu/mtrr/main-xen.c 2008-01-28 12:24:18.000000000 +0100 +@@ -0,0 +1,198 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include "mtrr.h" ++ ++static DEFINE_MUTEX(mtrr_mutex); ++ ++void generic_get_mtrr(unsigned int reg, unsigned long *base, ++ unsigned int *size, mtrr_type * type) ++{ ++ struct xen_platform_op op; ++ ++ op.cmd = XENPF_read_memtype; ++ op.u.read_memtype.reg = reg; ++ if (unlikely(HYPERVISOR_platform_op(&op))) ++ memset(&op.u.read_memtype, 0, sizeof(op.u.read_memtype)); ++ ++ *size = op.u.read_memtype.nr_mfns; ++ *base = op.u.read_memtype.mfn; ++ *type = op.u.read_memtype.type; ++} ++ ++struct mtrr_ops generic_mtrr_ops = { ++ .use_intel_if = 1, ++ .get = generic_get_mtrr, ++}; ++ ++struct mtrr_ops *mtrr_if = &generic_mtrr_ops; ++unsigned int num_var_ranges; ++unsigned int *usage_table; ++ ++static void __init set_num_var_ranges(void) ++{ ++ struct xen_platform_op op; ++ ++ for (num_var_ranges = 0; ; num_var_ranges++) { ++ op.cmd = XENPF_read_memtype; ++ op.u.read_memtype.reg = num_var_ranges; ++ if (HYPERVISOR_platform_op(&op) != 0) ++ break; ++ } ++} ++ ++static void __init init_table(void) ++{ ++ int i, max; ++ ++ max = num_var_ranges; ++ if ((usage_table = kmalloc(max * sizeof *usage_table, GFP_KERNEL)) ++ == NULL) { ++ printk(KERN_ERR "mtrr: could not allocate\n"); ++ return; ++ } ++ for (i = 0; i < max; i++) ++ usage_table[i] = 0; ++} ++ ++int mtrr_add_page(unsigned long base, unsigned long size, ++ unsigned int type, char increment) ++{ ++ int error; ++ struct xen_platform_op op; ++ ++ mutex_lock(&mtrr_mutex); ++ ++ op.cmd = XENPF_add_memtype; ++ op.u.add_memtype.mfn = base; ++ op.u.add_memtype.nr_mfns = size; ++ op.u.add_memtype.type = type; ++ error = HYPERVISOR_platform_op(&op); ++ if (error) { ++ mutex_unlock(&mtrr_mutex); ++ BUG_ON(error > 0); ++ return error; ++ } ++ ++ if (increment) ++ ++usage_table[op.u.add_memtype.reg]; ++ ++ mutex_unlock(&mtrr_mutex); ++ ++ return op.u.add_memtype.reg; ++} ++ ++static int mtrr_check(unsigned long base, unsigned long size) ++{ ++ if ((base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1))) { ++ printk(KERN_WARNING ++ "mtrr: size and base must be multiples of 4 kiB\n"); ++ printk(KERN_DEBUG ++ "mtrr: size: 0x%lx base: 0x%lx\n", size, base); ++ dump_stack(); ++ return -1; ++ } ++ return 0; ++} ++ ++int ++mtrr_add(unsigned long base, unsigned long size, unsigned int type, ++ char increment) ++{ ++ if (mtrr_check(base, size)) ++ return -EINVAL; ++ return mtrr_add_page(base >> PAGE_SHIFT, size >> PAGE_SHIFT, type, ++ increment); ++} ++ ++int mtrr_del_page(int reg, unsigned long base, unsigned long size) ++{ ++ unsigned i; ++ mtrr_type ltype; ++ unsigned long lbase; ++ unsigned int lsize; ++ int error = -EINVAL; ++ struct xen_platform_op op; ++ ++ mutex_lock(&mtrr_mutex); ++ ++ if (reg < 0) { ++ /* Search for existing MTRR */ ++ for (i = 0; i < num_var_ranges; ++i) { ++ mtrr_if->get(i, &lbase, &lsize, <ype); ++ if (lbase == base && lsize == size) { ++ reg = i; ++ break; ++ } ++ } ++ if (reg < 0) { ++ printk(KERN_DEBUG "mtrr: no MTRR for %lx000,%lx000 found\n", base, ++ size); ++ goto out; ++ } ++ } ++ if (usage_table[reg] < 1) { ++ printk(KERN_WARNING "mtrr: reg: %d has count=0\n", reg); ++ goto out; ++ } ++ if (--usage_table[reg] < 1) { ++ op.cmd = XENPF_del_memtype; ++ op.u.del_memtype.handle = 0; ++ op.u.del_memtype.reg = reg; ++ error = HYPERVISOR_platform_op(&op); ++ if (error) { ++ BUG_ON(error > 0); ++ goto out; ++ } ++ } ++ error = reg; ++ out: ++ mutex_unlock(&mtrr_mutex); ++ return error; ++} ++ ++int ++mtrr_del(int reg, unsigned long base, unsigned long size) ++{ ++ if (mtrr_check(base, size)) ++ return -EINVAL; ++ return mtrr_del_page(reg, base >> PAGE_SHIFT, size >> PAGE_SHIFT); ++} ++ ++EXPORT_SYMBOL(mtrr_add); ++EXPORT_SYMBOL(mtrr_del); ++ ++void __init mtrr_bp_init(void) ++{ ++} ++ ++void mtrr_ap_init(void) ++{ ++} ++ ++static int __init mtrr_init(void) ++{ ++ struct cpuinfo_x86 *c = &boot_cpu_data; ++ ++ if (!is_initial_xendomain()) ++ return -ENODEV; ++ ++ if ((!cpu_has(c, X86_FEATURE_MTRR)) && ++ (!cpu_has(c, X86_FEATURE_K6_MTRR)) && ++ (!cpu_has(c, X86_FEATURE_CYRIX_ARR)) && ++ (!cpu_has(c, X86_FEATURE_CENTAUR_MCR))) ++ return -ENODEV; ++ ++ set_num_var_ranges(); ++ init_table(); ++ ++ return 0; ++} ++ ++subsys_initcall(mtrr_init); +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/arch/x86/kernel/entry_32-xen.S 2009-05-19 09:16:41.000000000 +0200 +@@ -0,0 +1,1242 @@ ++/* ++ * linux/arch/i386/entry.S ++ * ++ * Copyright (C) 1991, 1992 Linus Torvalds ++ */ ++ ++/* ++ * entry.S contains the system-call and fault low-level handling routines. ++ * This also contains the timer-interrupt handler, as well as all interrupts ++ * and faults that can result in a task-switch. ++ * ++ * NOTE: This code handles signal-recognition, which happens every time ++ * after a timer-interrupt and after each system call. ++ * ++ * I changed all the .align's to 4 (16 byte alignment), as that's faster ++ * on a 486. ++ * ++ * Stack layout in 'ret_from_system_call': ++ * ptrace needs to have all regs on the stack. ++ * if the order here is changed, it needs to be ++ * updated in fork.c:copy_process, signal.c:do_signal, ++ * ptrace.c and ptrace.h ++ * ++ * 0(%esp) - %ebx ++ * 4(%esp) - %ecx ++ * 8(%esp) - %edx ++ * C(%esp) - %esi ++ * 10(%esp) - %edi ++ * 14(%esp) - %ebp ++ * 18(%esp) - %eax ++ * 1C(%esp) - %ds ++ * 20(%esp) - %es ++ * 24(%esp) - orig_eax ++ * 28(%esp) - %eip ++ * 2C(%esp) - %cs ++ * 30(%esp) - %eflags ++ * 34(%esp) - %oldesp ++ * 38(%esp) - %oldss ++ * ++ * "current" is in register %ebx during any slow entries. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "irq_vectors.h" ++#include ++ ++#define nr_syscalls ((syscall_table_size)/4) ++ ++EBX = 0x00 ++ECX = 0x04 ++EDX = 0x08 ++ESI = 0x0C ++EDI = 0x10 ++EBP = 0x14 ++EAX = 0x18 ++DS = 0x1C ++ES = 0x20 ++ORIG_EAX = 0x24 ++EIP = 0x28 ++CS = 0x2C ++EFLAGS = 0x30 ++OLDESP = 0x34 ++OLDSS = 0x38 ++ ++CF_MASK = 0x00000001 ++TF_MASK = 0x00000100 ++IF_MASK = 0x00000200 ++DF_MASK = 0x00000400 ++NT_MASK = 0x00004000 ++VM_MASK = 0x00020000 ++/* Pseudo-eflags. */ ++NMI_MASK = 0x80000000 ++ ++#ifndef CONFIG_XEN ++#define DISABLE_INTERRUPTS cli ++#define ENABLE_INTERRUPTS sti ++#else ++/* Offsets into shared_info_t. */ ++#define evtchn_upcall_pending /* 0 */ ++#define evtchn_upcall_mask 1 ++ ++#define sizeof_vcpu_shift 6 ++ ++#ifdef CONFIG_SMP ++#define GET_VCPU_INFO movl TI_cpu(%ebp),%esi ; \ ++ shl $sizeof_vcpu_shift,%esi ; \ ++ addl HYPERVISOR_shared_info,%esi ++#else ++#define GET_VCPU_INFO movl HYPERVISOR_shared_info,%esi ++#endif ++ ++#define __DISABLE_INTERRUPTS movb $1,evtchn_upcall_mask(%esi) ++#define __ENABLE_INTERRUPTS movb $0,evtchn_upcall_mask(%esi) ++#define DISABLE_INTERRUPTS GET_VCPU_INFO ; \ ++ __DISABLE_INTERRUPTS ++#define ENABLE_INTERRUPTS GET_VCPU_INFO ; \ ++ __ENABLE_INTERRUPTS ++#define __TEST_PENDING testb $0xFF,evtchn_upcall_pending(%esi) ++#endif ++ ++#ifdef CONFIG_PREEMPT ++#define preempt_stop cli; TRACE_IRQS_OFF ++#else ++#define preempt_stop ++#define resume_kernel restore_nocheck ++#endif ++ ++.macro TRACE_IRQS_IRET ++#ifdef CONFIG_TRACE_IRQFLAGS ++ testl $IF_MASK,EFLAGS(%esp) # interrupts off? ++ jz 1f ++ TRACE_IRQS_ON ++1: ++#endif ++.endm ++ ++#ifdef CONFIG_VM86 ++#define resume_userspace_sig check_userspace ++#else ++#define resume_userspace_sig resume_userspace ++#endif ++ ++#define SAVE_ALL \ ++ cld; \ ++ pushl %es; \ ++ CFI_ADJUST_CFA_OFFSET 4;\ ++ /*CFI_REL_OFFSET es, 0;*/\ ++ pushl %ds; \ ++ CFI_ADJUST_CFA_OFFSET 4;\ ++ /*CFI_REL_OFFSET ds, 0;*/\ ++ pushl %eax; \ ++ CFI_ADJUST_CFA_OFFSET 4;\ ++ CFI_REL_OFFSET eax, 0;\ ++ pushl %ebp; \ ++ CFI_ADJUST_CFA_OFFSET 4;\ ++ CFI_REL_OFFSET ebp, 0;\ ++ pushl %edi; \ ++ CFI_ADJUST_CFA_OFFSET 4;\ ++ CFI_REL_OFFSET edi, 0;\ ++ pushl %esi; \ ++ CFI_ADJUST_CFA_OFFSET 4;\ ++ CFI_REL_OFFSET esi, 0;\ ++ pushl %edx; \ ++ CFI_ADJUST_CFA_OFFSET 4;\ ++ CFI_REL_OFFSET edx, 0;\ ++ pushl %ecx; \ ++ CFI_ADJUST_CFA_OFFSET 4;\ ++ CFI_REL_OFFSET ecx, 0;\ ++ pushl %ebx; \ ++ CFI_ADJUST_CFA_OFFSET 4;\ ++ CFI_REL_OFFSET ebx, 0;\ ++ movl $(__USER_DS), %edx; \ ++ movl %edx, %ds; \ ++ movl %edx, %es; ++ ++#define RESTORE_INT_REGS \ ++ popl %ebx; \ ++ CFI_ADJUST_CFA_OFFSET -4;\ ++ CFI_RESTORE ebx;\ ++ popl %ecx; \ ++ CFI_ADJUST_CFA_OFFSET -4;\ ++ CFI_RESTORE ecx;\ ++ popl %edx; \ ++ CFI_ADJUST_CFA_OFFSET -4;\ ++ CFI_RESTORE edx;\ ++ popl %esi; \ ++ CFI_ADJUST_CFA_OFFSET -4;\ ++ CFI_RESTORE esi;\ ++ popl %edi; \ ++ CFI_ADJUST_CFA_OFFSET -4;\ ++ CFI_RESTORE edi;\ ++ popl %ebp; \ ++ CFI_ADJUST_CFA_OFFSET -4;\ ++ CFI_RESTORE ebp;\ ++ popl %eax; \ ++ CFI_ADJUST_CFA_OFFSET -4;\ ++ CFI_RESTORE eax ++ ++#define RESTORE_REGS \ ++ RESTORE_INT_REGS; \ ++1: popl %ds; \ ++ CFI_ADJUST_CFA_OFFSET -4;\ ++ /*CFI_RESTORE ds;*/\ ++2: popl %es; \ ++ CFI_ADJUST_CFA_OFFSET -4;\ ++ /*CFI_RESTORE es;*/\ ++.section .fixup,"ax"; \ ++3: movl $0,(%esp); \ ++ jmp 1b; \ ++4: movl $0,(%esp); \ ++ jmp 2b; \ ++.previous; \ ++.section __ex_table,"a";\ ++ .align 4; \ ++ .long 1b,3b; \ ++ .long 2b,4b; \ ++.previous ++ ++#define RING0_INT_FRAME \ ++ CFI_STARTPROC simple;\ ++ CFI_DEF_CFA esp, 3*4;\ ++ /*CFI_OFFSET cs, -2*4;*/\ ++ CFI_OFFSET eip, -3*4 ++ ++#define RING0_EC_FRAME \ ++ CFI_STARTPROC simple;\ ++ CFI_DEF_CFA esp, 4*4;\ ++ /*CFI_OFFSET cs, -2*4;*/\ ++ CFI_OFFSET eip, -3*4 ++ ++#define RING0_PTREGS_FRAME \ ++ CFI_STARTPROC simple;\ ++ CFI_DEF_CFA esp, OLDESP-EBX;\ ++ /*CFI_OFFSET cs, CS-OLDESP;*/\ ++ CFI_OFFSET eip, EIP-OLDESP;\ ++ /*CFI_OFFSET es, ES-OLDESP;*/\ ++ /*CFI_OFFSET ds, DS-OLDESP;*/\ ++ CFI_OFFSET eax, EAX-OLDESP;\ ++ CFI_OFFSET ebp, EBP-OLDESP;\ ++ CFI_OFFSET edi, EDI-OLDESP;\ ++ CFI_OFFSET esi, ESI-OLDESP;\ ++ CFI_OFFSET edx, EDX-OLDESP;\ ++ CFI_OFFSET ecx, ECX-OLDESP;\ ++ CFI_OFFSET ebx, EBX-OLDESP ++ ++ENTRY(ret_from_fork) ++ CFI_STARTPROC ++ pushl %eax ++ CFI_ADJUST_CFA_OFFSET 4 ++ call schedule_tail ++ GET_THREAD_INFO(%ebp) ++ popl %eax ++ CFI_ADJUST_CFA_OFFSET -4 ++ pushl $0x0202 # Reset kernel eflags ++ CFI_ADJUST_CFA_OFFSET 4 ++ popfl ++ CFI_ADJUST_CFA_OFFSET -4 ++ jmp syscall_exit ++ CFI_ENDPROC ++ ++/* ++ * Return to user mode is not as complex as all this looks, ++ * but we want the default path for a system call return to ++ * go as quickly as possible which is why some of this is ++ * less clear than it otherwise should be. ++ */ ++ ++ # userspace resumption stub bypassing syscall exit tracing ++ ALIGN ++ RING0_PTREGS_FRAME ++ret_from_exception: ++ preempt_stop ++ret_from_intr: ++ GET_THREAD_INFO(%ebp) ++check_userspace: ++ movl EFLAGS(%esp), %eax # mix EFLAGS and CS ++ movb CS(%esp), %al ++ testl $(VM_MASK | 2), %eax ++ jz resume_kernel ++ENTRY(resume_userspace) ++ DISABLE_INTERRUPTS # make sure we don't miss an interrupt ++ # setting need_resched or sigpending ++ # between sampling and the iret ++ movl TI_flags(%ebp), %ecx ++ andl $_TIF_WORK_MASK, %ecx # is there any work to be done on ++ # int/exception return? ++ jne work_pending ++ jmp restore_all ++ ++#ifdef CONFIG_PREEMPT ++ENTRY(resume_kernel) ++ cli ++ cmpl $0,TI_preempt_count(%ebp) # non-zero preempt_count ? ++ jnz restore_nocheck ++need_resched: ++ movl TI_flags(%ebp), %ecx # need_resched set ? ++ testb $_TIF_NEED_RESCHED, %cl ++ jz restore_all ++ testl $IF_MASK,EFLAGS(%esp) # interrupts off (exception path) ? ++ jz restore_all ++ call preempt_schedule_irq ++ jmp need_resched ++#endif ++ CFI_ENDPROC ++ ++/* SYSENTER_RETURN points to after the "sysenter" instruction in ++ the vsyscall page. See vsyscall-sysentry.S, which defines the symbol. */ ++ ++ # sysenter call handler stub ++ENTRY(sysenter_entry) ++ CFI_STARTPROC simple ++ CFI_DEF_CFA esp, 0 ++ CFI_REGISTER esp, ebp ++ movl SYSENTER_stack_esp0(%esp),%esp ++sysenter_past_esp: ++ /* ++ * No need to follow this irqs on/off section: the syscall ++ * disabled irqs and here we enable it straight after entry: ++ */ ++ sti ++ pushl $(__USER_DS) ++ CFI_ADJUST_CFA_OFFSET 4 ++ /*CFI_REL_OFFSET ss, 0*/ ++ pushl %ebp ++ CFI_ADJUST_CFA_OFFSET 4 ++ CFI_REL_OFFSET esp, 0 ++ pushfl ++ CFI_ADJUST_CFA_OFFSET 4 ++ pushl $(__USER_CS) ++ CFI_ADJUST_CFA_OFFSET 4 ++ /*CFI_REL_OFFSET cs, 0*/ ++ /* ++ * Push current_thread_info()->sysenter_return to the stack. ++ * A tiny bit of offset fixup is necessary - 4*4 means the 4 words ++ * pushed above; +8 corresponds to copy_thread's esp0 setting. ++ */ ++ pushl (TI_sysenter_return-THREAD_SIZE+8+4*4)(%esp) ++ CFI_ADJUST_CFA_OFFSET 4 ++ CFI_REL_OFFSET eip, 0 ++ ++/* ++ * Load the potential sixth argument from user stack. ++ * Careful about security. ++ */ ++ cmpl $__PAGE_OFFSET-3,%ebp ++ jae syscall_fault ++1: movl (%ebp),%ebp ++.section __ex_table,"a" ++ .align 4 ++ .long 1b,syscall_fault ++.previous ++ ++ pushl %eax ++ CFI_ADJUST_CFA_OFFSET 4 ++ SAVE_ALL ++ GET_THREAD_INFO(%ebp) ++ ++ /* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not testb */ ++ testw $(_TIF_SYSCALL_EMU|_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT),TI_flags(%ebp) ++ jnz syscall_trace_entry ++ cmpl $(nr_syscalls), %eax ++ jae syscall_badsys ++ call *sys_call_table(,%eax,4) ++ movl %eax,EAX(%esp) ++ DISABLE_INTERRUPTS ++ TRACE_IRQS_OFF ++ movl TI_flags(%ebp), %ecx ++ testw $_TIF_ALLWORK_MASK, %cx ++ jne syscall_exit_work ++/* if something modifies registers it must also disable sysexit */ ++ movl EIP(%esp), %edx ++ movl OLDESP(%esp), %ecx ++ xorl %ebp,%ebp ++#ifdef CONFIG_XEN ++ TRACE_IRQS_ON ++ __ENABLE_INTERRUPTS ++sysexit_scrit: /**** START OF SYSEXIT CRITICAL REGION ****/ ++ __TEST_PENDING ++ jnz 14f # process more events if necessary... ++ movl ESI(%esp), %esi ++ sysexit ++14: __DISABLE_INTERRUPTS ++ TRACE_IRQS_OFF ++sysexit_ecrit: /**** END OF SYSEXIT CRITICAL REGION ****/ ++ push %esp ++ call evtchn_do_upcall ++ add $4,%esp ++ jmp ret_from_intr ++#else ++ TRACE_IRQS_ON ++ sti ++ sysexit ++#endif /* !CONFIG_XEN */ ++ CFI_ENDPROC ++ ++ # pv sysenter call handler stub ++ENTRY(sysenter_entry_pv) ++ RING0_INT_FRAME ++ movl $__USER_DS,16(%esp) ++ movl %ebp,12(%esp) ++ movl $__USER_CS,4(%esp) ++ addl $4,%esp ++ CFI_ADJUST_CFA_OFFSET -4 ++ /* +5*4 is SS:ESP,EFLAGS,CS:EIP. +8 is esp0 setting. */ ++ pushl (TI_sysenter_return-THREAD_SIZE+8+4*4)(%esp) ++ CFI_ADJUST_CFA_OFFSET 4 ++/* ++ * Load the potential sixth argument from user stack. ++ * Careful about security. ++ */ ++ cmpl $__PAGE_OFFSET-3,%ebp ++ jae syscall_fault ++1: movl (%ebp),%ebp ++.section __ex_table,"a" ++ .align 4 ++ .long 1b,syscall_fault ++.previous ++ /* fall through */ ++ CFI_ENDPROC ++ENDPROC(sysenter_entry_pv) ++ ++ # system call handler stub ++ENTRY(system_call) ++ RING0_INT_FRAME # can't unwind into user space anyway ++ pushl %eax # save orig_eax ++ CFI_ADJUST_CFA_OFFSET 4 ++ SAVE_ALL ++ GET_THREAD_INFO(%ebp) ++ testl $TF_MASK,EFLAGS(%esp) ++ jz no_singlestep ++ orl $_TIF_SINGLESTEP,TI_flags(%ebp) ++no_singlestep: ++ # system call tracing in operation / emulation ++ /* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not testb */ ++ testw $(_TIF_SYSCALL_EMU|_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT),TI_flags(%ebp) ++ jnz syscall_trace_entry ++ cmpl $(nr_syscalls), %eax ++ jae syscall_badsys ++syscall_call: ++ call *sys_call_table(,%eax,4) ++ movl %eax,EAX(%esp) # store the return value ++syscall_exit: ++ DISABLE_INTERRUPTS # make sure we don't miss an interrupt ++ # setting need_resched or sigpending ++ # between sampling and the iret ++ TRACE_IRQS_OFF ++ movl TI_flags(%ebp), %ecx ++ testw $_TIF_ALLWORK_MASK, %cx # current->work ++ jne syscall_exit_work ++ ++restore_all: ++#ifndef CONFIG_XEN ++ movl EFLAGS(%esp), %eax # mix EFLAGS, SS and CS ++ # Warning: OLDSS(%esp) contains the wrong/random values if we ++ # are returning to the kernel. ++ # See comments in process.c:copy_thread() for details. ++ movb OLDSS(%esp), %ah ++ movb CS(%esp), %al ++ andl $(VM_MASK | (4 << 8) | 3), %eax ++ cmpl $((4 << 8) | 3), %eax ++ CFI_REMEMBER_STATE ++ je ldt_ss # returning to user-space with LDT SS ++restore_nocheck: ++#else ++restore_nocheck: ++ movl EFLAGS(%esp), %eax ++ testl $(VM_MASK|NMI_MASK), %eax ++ CFI_REMEMBER_STATE ++ jnz hypervisor_iret ++ shr $9, %eax # EAX[0] == IRET_EFLAGS.IF ++ GET_VCPU_INFO ++ andb evtchn_upcall_mask(%esi),%al ++ andb $1,%al # EAX[0] == IRET_EFLAGS.IF & event_mask ++ CFI_REMEMBER_STATE ++ jnz restore_all_enable_events # != 0 => enable event delivery ++#endif ++ TRACE_IRQS_IRET ++restore_nocheck_notrace: ++ RESTORE_REGS ++ addl $4, %esp ++ CFI_ADJUST_CFA_OFFSET -4 ++1: iret ++.section .fixup,"ax" ++iret_exc: ++#ifndef CONFIG_XEN ++ TRACE_IRQS_ON ++ sti ++#endif ++ pushl $0 # no error code ++ pushl $do_iret_error ++ jmp error_code ++.previous ++.section __ex_table,"a" ++ .align 4 ++ .long 1b,iret_exc ++.previous ++ ++ CFI_RESTORE_STATE ++#ifndef CONFIG_XEN ++ldt_ss: ++ larl OLDSS(%esp), %eax ++ jnz restore_nocheck ++ testl $0x00400000, %eax # returning to 32bit stack? ++ jnz restore_nocheck # allright, normal return ++ /* If returning to userspace with 16bit stack, ++ * try to fix the higher word of ESP, as the CPU ++ * won't restore it. ++ * This is an "official" bug of all the x86-compatible ++ * CPUs, which we can try to work around to make ++ * dosemu and wine happy. */ ++ subl $8, %esp # reserve space for switch16 pointer ++ CFI_ADJUST_CFA_OFFSET 8 ++ cli ++ TRACE_IRQS_OFF ++ movl %esp, %eax ++ /* Set up the 16bit stack frame with switch32 pointer on top, ++ * and a switch16 pointer on top of the current frame. */ ++ call setup_x86_bogus_stack ++ CFI_ADJUST_CFA_OFFSET -8 # frame has moved ++ TRACE_IRQS_IRET ++ RESTORE_REGS ++ lss 20+4(%esp), %esp # switch to 16bit stack ++1: iret ++.section __ex_table,"a" ++ .align 4 ++ .long 1b,iret_exc ++.previous ++#else ++ ALIGN ++restore_all_enable_events: ++ TRACE_IRQS_ON ++ __ENABLE_INTERRUPTS ++scrit: /**** START OF CRITICAL REGION ****/ ++ __TEST_PENDING ++ jnz 14f # process more events if necessary... ++ RESTORE_REGS ++ addl $4, %esp ++ CFI_ADJUST_CFA_OFFSET -4 ++1: iret ++.section __ex_table,"a" ++ .align 4 ++ .long 1b,iret_exc ++.previous ++14: __DISABLE_INTERRUPTS ++ TRACE_IRQS_OFF ++ecrit: /**** END OF CRITICAL REGION ****/ ++ jmp .Ldo_upcall ++ ++ CFI_RESTORE_STATE ++hypervisor_iret: ++ andl $~NMI_MASK, EFLAGS(%esp) ++ RESTORE_REGS ++ addl $4, %esp ++ CFI_ADJUST_CFA_OFFSET -4 ++ jmp hypercall_page + (__HYPERVISOR_iret * 32) ++#endif ++ CFI_ENDPROC ++ ++ # perform work that needs to be done immediately before resumption ++ ALIGN ++ RING0_PTREGS_FRAME # can't unwind into user space anyway ++work_pending: ++ testb $_TIF_NEED_RESCHED, %cl ++ jz work_notifysig ++work_resched: ++ call schedule ++ DISABLE_INTERRUPTS # make sure we don't miss an interrupt ++ # setting need_resched or sigpending ++ # between sampling and the iret ++ TRACE_IRQS_OFF ++ movl TI_flags(%ebp), %ecx ++ andl $_TIF_WORK_MASK, %ecx # is there any work to be done other ++ # than syscall tracing? ++ jz restore_all ++ testb $_TIF_NEED_RESCHED, %cl ++ jnz work_resched ++ ++work_notifysig: # deal with pending signals and ++ # notify-resume requests ++ testl $VM_MASK, EFLAGS(%esp) ++ movl %esp, %eax ++ jne work_notifysig_v86 # returning to kernel-space or ++ # vm86-space ++ xorl %edx, %edx ++ call do_notify_resume ++ jmp resume_userspace_sig ++ ++ ALIGN ++work_notifysig_v86: ++#ifdef CONFIG_VM86 ++ pushl %ecx # save ti_flags for do_notify_resume ++ CFI_ADJUST_CFA_OFFSET 4 ++ call save_v86_state # %eax contains pt_regs pointer ++ popl %ecx ++ CFI_ADJUST_CFA_OFFSET -4 ++ movl %eax, %esp ++ xorl %edx, %edx ++ call do_notify_resume ++ jmp resume_userspace_sig ++#endif ++ ++ # perform syscall exit tracing ++ ALIGN ++syscall_trace_entry: ++ movl $-ENOSYS,EAX(%esp) ++ movl %esp, %eax ++ xorl %edx,%edx ++ call do_syscall_trace ++ cmpl $0, %eax ++ jne resume_userspace # ret != 0 -> running under PTRACE_SYSEMU, ++ # so must skip actual syscall ++ movl ORIG_EAX(%esp), %eax ++ cmpl $(nr_syscalls), %eax ++ jnae syscall_call ++ jmp syscall_exit ++ ++ # perform syscall exit tracing ++ ALIGN ++syscall_exit_work: ++ testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP), %cl ++ jz work_pending ++ TRACE_IRQS_ON ++ ENABLE_INTERRUPTS # could let do_syscall_trace() call ++ # schedule() instead ++ movl %esp, %eax ++ movl $1, %edx ++ call do_syscall_trace ++ jmp resume_userspace ++ CFI_ENDPROC ++ ++ RING0_INT_FRAME # can't unwind into user space anyway ++syscall_fault: ++ pushl %eax # save orig_eax ++ CFI_ADJUST_CFA_OFFSET 4 ++ SAVE_ALL ++ GET_THREAD_INFO(%ebp) ++ movl $-EFAULT,EAX(%esp) ++ jmp resume_userspace ++ ++syscall_badsys: ++ movl $-ENOSYS,EAX(%esp) ++ jmp resume_userspace ++ CFI_ENDPROC ++ ++#ifndef CONFIG_XEN ++#define FIXUP_ESPFIX_STACK \ ++ movl %esp, %eax; \ ++ /* switch to 32bit stack using the pointer on top of 16bit stack */ \ ++ lss %ss:CPU_16BIT_STACK_SIZE-8, %esp; \ ++ /* copy data from 16bit stack to 32bit stack */ \ ++ call fixup_x86_bogus_stack; \ ++ /* put ESP to the proper location */ \ ++ movl %eax, %esp; ++#define UNWIND_ESPFIX_STACK \ ++ pushl %eax; \ ++ CFI_ADJUST_CFA_OFFSET 4; \ ++ movl %ss, %eax; \ ++ /* see if on 16bit stack */ \ ++ cmpw $__ESPFIX_SS, %ax; \ ++ je 28f; \ ++27: popl %eax; \ ++ CFI_ADJUST_CFA_OFFSET -4; \ ++.section .fixup,"ax"; \ ++28: movl $__KERNEL_DS, %eax; \ ++ movl %eax, %ds; \ ++ movl %eax, %es; \ ++ /* switch to 32bit stack */ \ ++ FIXUP_ESPFIX_STACK; \ ++ jmp 27b; \ ++.previous ++ ++/* ++ * Build the entry stubs and pointer table with ++ * some assembler magic. ++ */ ++.data ++ENTRY(interrupt) ++.text ++ ++vector=0 ++ENTRY(irq_entries_start) ++ RING0_INT_FRAME ++.rept NR_IRQS ++ ALIGN ++ .if vector ++ CFI_ADJUST_CFA_OFFSET -4 ++ .endif ++1: pushl $~(vector) ++ CFI_ADJUST_CFA_OFFSET 4 ++ jmp common_interrupt ++.data ++ .long 1b ++.text ++vector=vector+1 ++.endr ++ ++/* ++ * the CPU automatically disables interrupts when executing an IRQ vector, ++ * so IRQ-flags tracing has to follow that: ++ */ ++ ALIGN ++common_interrupt: ++ SAVE_ALL ++ TRACE_IRQS_OFF ++ movl %esp,%eax ++ call do_IRQ ++ jmp ret_from_intr ++ CFI_ENDPROC ++ ++#define BUILD_INTERRUPT(name, nr) \ ++ENTRY(name) \ ++ RING0_INT_FRAME; \ ++ pushl $~(nr); \ ++ CFI_ADJUST_CFA_OFFSET 4; \ ++ SAVE_ALL; \ ++ TRACE_IRQS_OFF \ ++ movl %esp,%eax; \ ++ call smp_/**/name; \ ++ jmp ret_from_intr; \ ++ CFI_ENDPROC ++ ++/* The include is where all of the SMP etc. interrupts come from */ ++#include "entry_arch.h" ++#else ++#define UNWIND_ESPFIX_STACK ++#endif ++ ++ENTRY(divide_error) ++ RING0_INT_FRAME ++ pushl $0 # no error code ++ CFI_ADJUST_CFA_OFFSET 4 ++ pushl $do_divide_error ++ CFI_ADJUST_CFA_OFFSET 4 ++ ALIGN ++error_code: ++ pushl %ds ++ CFI_ADJUST_CFA_OFFSET 4 ++ /*CFI_REL_OFFSET ds, 0*/ ++ pushl %eax ++ CFI_ADJUST_CFA_OFFSET 4 ++ CFI_REL_OFFSET eax, 0 ++ xorl %eax, %eax ++ pushl %ebp ++ CFI_ADJUST_CFA_OFFSET 4 ++ CFI_REL_OFFSET ebp, 0 ++ pushl %edi ++ CFI_ADJUST_CFA_OFFSET 4 ++ CFI_REL_OFFSET edi, 0 ++ pushl %esi ++ CFI_ADJUST_CFA_OFFSET 4 ++ CFI_REL_OFFSET esi, 0 ++ pushl %edx ++ CFI_ADJUST_CFA_OFFSET 4 ++ CFI_REL_OFFSET edx, 0 ++ decl %eax # eax = -1 ++ pushl %ecx ++ CFI_ADJUST_CFA_OFFSET 4 ++ CFI_REL_OFFSET ecx, 0 ++ pushl %ebx ++ CFI_ADJUST_CFA_OFFSET 4 ++ CFI_REL_OFFSET ebx, 0 ++ cld ++ pushl %es ++ CFI_ADJUST_CFA_OFFSET 4 ++ /*CFI_REL_OFFSET es, 0*/ ++ UNWIND_ESPFIX_STACK ++ popl %ecx ++ CFI_ADJUST_CFA_OFFSET -4 ++ /*CFI_REGISTER es, ecx*/ ++ movl ES(%esp), %edi # get the function address ++ movl ORIG_EAX(%esp), %edx # get the error code ++ movl %eax, ORIG_EAX(%esp) ++ movl %ecx, ES(%esp) ++ /*CFI_REL_OFFSET es, ES*/ ++ movl $(__USER_DS), %ecx ++ movl %ecx, %ds ++ movl %ecx, %es ++ movl %esp,%eax # pt_regs pointer ++ call *%edi ++ jmp ret_from_exception ++ CFI_ENDPROC ++ ++#ifdef CONFIG_XEN ++# A note on the "critical region" in our callback handler. ++# We want to avoid stacking callback handlers due to events occurring ++# during handling of the last event. To do this, we keep events disabled ++# until we've done all processing. HOWEVER, we must enable events before ++# popping the stack frame (can't be done atomically) and so it would still ++# be possible to get enough handler activations to overflow the stack. ++# Although unlikely, bugs of that kind are hard to track down, so we'd ++# like to avoid the possibility. ++# So, on entry to the handler we detect whether we interrupted an ++# existing activation in its critical region -- if so, we pop the current ++# activation and restart the handler using the previous one. ++# ++# The sysexit critical region is slightly different. sysexit ++# atomically removes the entire stack frame. If we interrupt in the ++# critical region we know that the entire frame is present and correct ++# so we can simply throw away the new one. ++ENTRY(hypervisor_callback) ++ RING0_INT_FRAME ++ pushl %eax ++ CFI_ADJUST_CFA_OFFSET 4 ++ SAVE_ALL ++ testb $2,CS(%esp) ++ movl EIP(%esp),%eax ++ jnz .Ldo_upcall ++ cmpl $scrit,%eax ++ jb 0f ++ cmpl $ecrit,%eax ++ jb critical_region_fixup ++0: ++#ifdef CONFIG_XEN_SUPERVISOR_MODE_KERNEL ++ cmpl $sysexit_scrit,%eax ++ jb .Ldo_upcall ++ cmpl $sysexit_ecrit,%eax ++ ja .Ldo_upcall ++ addl $OLDESP,%esp # Remove eflags...ebx from stack frame. ++#endif ++.Ldo_upcall: ++ push %esp ++ CFI_ADJUST_CFA_OFFSET 4 ++ call evtchn_do_upcall ++ add $4,%esp ++ CFI_ADJUST_CFA_OFFSET -4 ++ jmp ret_from_intr ++ CFI_ENDPROC ++ ++# [How we do the fixup]. We want to merge the current stack frame with the ++# just-interrupted frame. How we do this depends on where in the critical ++# region the interrupted handler was executing, and so how many saved ++# registers are in each frame. We do this quickly using the lookup table ++# 'critical_fixup_table'. For each byte offset in the critical region, it ++# provides the number of bytes which have already been popped from the ++# interrupted stack frame. ++critical_region_fixup: ++ movsbl critical_fixup_table-scrit(%eax),%ecx # %ecx contains num slots popped ++ testl %ecx,%ecx ++ leal (%esp,%ecx,4),%esi # %esi points at end of src region ++ leal OLDESP(%esp),%edi # %edi points at end of dst region ++ jle 17f # skip loop if nothing to copy ++16: subl $4,%esi # pre-decrementing copy loop ++ subl $4,%edi ++ movl (%esi),%eax ++ movl %eax,(%edi) ++ loop 16b ++17: movl %edi,%esp # final %edi is top of merged stack ++ jmp .Ldo_upcall ++ ++.section .rodata,"a" ++critical_fixup_table: ++ .byte -1,-1,-1 # testb $0xff,(%esi) = __TEST_PENDING ++ .byte -1,-1 # jnz 14f ++ .byte 0 # pop %ebx ++ .byte 1 # pop %ecx ++ .byte 2 # pop %edx ++ .byte 3 # pop %esi ++ .byte 4 # pop %edi ++ .byte 5 # pop %ebp ++ .byte 6 # pop %eax ++ .byte 7 # pop %ds ++ .byte 8 # pop %es ++ .byte 9,9,9 # add $4,%esp ++ .byte 10 # iret ++ .byte -1,-1,-1,-1 # movb $1,1(%esi) = __DISABLE_INTERRUPTS ++.previous ++ ++# Hypervisor uses this for application faults while it executes. ++# We get here for two reasons: ++# 1. Fault while reloading DS, ES, FS or GS ++# 2. Fault while executing IRET ++# Category 1 we fix up by reattempting the load, and zeroing the segment ++# register if the load fails. ++# Category 2 we fix up by jumping to do_iret_error. We cannot use the ++# normal Linux return path in this case because if we use the IRET hypercall ++# to pop the stack frame we end up in an infinite loop of failsafe callbacks. ++# We distinguish between categories by maintaining a status value in EAX. ++ENTRY(failsafe_callback) ++ pushl %eax ++ movl $1,%eax ++1: mov 4(%esp),%ds ++2: mov 8(%esp),%es ++3: mov 12(%esp),%fs ++4: mov 16(%esp),%gs ++ testl %eax,%eax ++ popl %eax ++ jz 5f ++ addl $16,%esp # EAX != 0 => Category 2 (Bad IRET) ++ jmp iret_exc ++5: addl $16,%esp # EAX == 0 => Category 1 (Bad segment) ++ RING0_INT_FRAME ++ pushl $0 ++ SAVE_ALL ++ jmp ret_from_exception ++.section .fixup,"ax"; \ ++6: xorl %eax,%eax; \ ++ movl %eax,4(%esp); \ ++ jmp 1b; \ ++7: xorl %eax,%eax; \ ++ movl %eax,8(%esp); \ ++ jmp 2b; \ ++8: xorl %eax,%eax; \ ++ movl %eax,12(%esp); \ ++ jmp 3b; \ ++9: xorl %eax,%eax; \ ++ movl %eax,16(%esp); \ ++ jmp 4b; \ ++.previous; \ ++.section __ex_table,"a"; \ ++ .align 4; \ ++ .long 1b,6b; \ ++ .long 2b,7b; \ ++ .long 3b,8b; \ ++ .long 4b,9b; \ ++.previous ++#endif ++ CFI_ENDPROC ++ ++ENTRY(coprocessor_error) ++ RING0_INT_FRAME ++ pushl $0 ++ CFI_ADJUST_CFA_OFFSET 4 ++ pushl $do_coprocessor_error ++ CFI_ADJUST_CFA_OFFSET 4 ++ jmp error_code ++ CFI_ENDPROC ++ ++ENTRY(simd_coprocessor_error) ++ RING0_INT_FRAME ++ pushl $0 ++ CFI_ADJUST_CFA_OFFSET 4 ++ pushl $do_simd_coprocessor_error ++ CFI_ADJUST_CFA_OFFSET 4 ++ jmp error_code ++ CFI_ENDPROC ++ ++ENTRY(device_not_available) ++ RING0_INT_FRAME ++ pushl $-1 # mark this as an int ++ CFI_ADJUST_CFA_OFFSET 4 ++ SAVE_ALL ++#ifndef CONFIG_XEN ++ movl %cr0, %eax ++ testl $0x4, %eax # EM (math emulation bit) ++ je device_available_emulate ++ pushl $0 # temporary storage for ORIG_EIP ++ CFI_ADJUST_CFA_OFFSET 4 ++ call math_emulate ++ addl $4, %esp ++ CFI_ADJUST_CFA_OFFSET -4 ++ jmp ret_from_exception ++device_available_emulate: ++#endif ++ preempt_stop ++ call math_state_restore ++ jmp ret_from_exception ++ CFI_ENDPROC ++ ++#ifndef CONFIG_XEN ++/* ++ * Debug traps and NMI can happen at the one SYSENTER instruction ++ * that sets up the real kernel stack. Check here, since we can't ++ * allow the wrong stack to be used. ++ * ++ * "SYSENTER_stack_esp0+12" is because the NMI/debug handler will have ++ * already pushed 3 words if it hits on the sysenter instruction: ++ * eflags, cs and eip. ++ * ++ * We just load the right stack, and push the three (known) values ++ * by hand onto the new stack - while updating the return eip past ++ * the instruction that would have done it for sysenter. ++ */ ++#define FIX_STACK(offset, ok, label) \ ++ cmpw $__KERNEL_CS,4(%esp); \ ++ jne ok; \ ++label: \ ++ movl SYSENTER_stack_esp0+offset(%esp),%esp; \ ++ pushfl; \ ++ pushl $__KERNEL_CS; \ ++ pushl $sysenter_past_esp ++#endif /* CONFIG_XEN */ ++ ++KPROBE_ENTRY(debug) ++ RING0_INT_FRAME ++#ifndef CONFIG_XEN ++ cmpl $sysenter_entry,(%esp) ++ jne debug_stack_correct ++ FIX_STACK(12, debug_stack_correct, debug_esp_fix_insn) ++debug_stack_correct: ++#endif /* !CONFIG_XEN */ ++ pushl $-1 # mark this as an int ++ CFI_ADJUST_CFA_OFFSET 4 ++ SAVE_ALL ++ xorl %edx,%edx # error code 0 ++ movl %esp,%eax # pt_regs pointer ++ call do_debug ++ jmp ret_from_exception ++ CFI_ENDPROC ++ .previous .text ++#ifndef CONFIG_XEN ++/* ++ * NMI is doubly nasty. It can happen _while_ we're handling ++ * a debug fault, and the debug fault hasn't yet been able to ++ * clear up the stack. So we first check whether we got an ++ * NMI on the sysenter entry path, but after that we need to ++ * check whether we got an NMI on the debug path where the debug ++ * fault happened on the sysenter path. ++ */ ++ENTRY(nmi) ++ RING0_INT_FRAME ++ pushl %eax ++ CFI_ADJUST_CFA_OFFSET 4 ++ movl %ss, %eax ++ cmpw $__ESPFIX_SS, %ax ++ popl %eax ++ CFI_ADJUST_CFA_OFFSET -4 ++ je nmi_16bit_stack ++ cmpl $sysenter_entry,(%esp) ++ je nmi_stack_fixup ++ pushl %eax ++ CFI_ADJUST_CFA_OFFSET 4 ++ movl %esp,%eax ++ /* Do not access memory above the end of our stack page, ++ * it might not exist. ++ */ ++ andl $(THREAD_SIZE-1),%eax ++ cmpl $(THREAD_SIZE-20),%eax ++ popl %eax ++ CFI_ADJUST_CFA_OFFSET -4 ++ jae nmi_stack_correct ++ cmpl $sysenter_entry,12(%esp) ++ je nmi_debug_stack_check ++nmi_stack_correct: ++ pushl %eax ++ CFI_ADJUST_CFA_OFFSET 4 ++ SAVE_ALL ++ xorl %edx,%edx # zero error code ++ movl %esp,%eax # pt_regs pointer ++ call do_nmi ++ jmp restore_nocheck_notrace ++ CFI_ENDPROC ++ ++nmi_stack_fixup: ++ FIX_STACK(12,nmi_stack_correct, 1) ++ jmp nmi_stack_correct ++nmi_debug_stack_check: ++ cmpw $__KERNEL_CS,16(%esp) ++ jne nmi_stack_correct ++ cmpl $debug,(%esp) ++ jb nmi_stack_correct ++ cmpl $debug_esp_fix_insn,(%esp) ++ ja nmi_stack_correct ++ FIX_STACK(24,nmi_stack_correct, 1) ++ jmp nmi_stack_correct ++ ++nmi_16bit_stack: ++ RING0_INT_FRAME ++ /* create the pointer to lss back */ ++ pushl %ss ++ CFI_ADJUST_CFA_OFFSET 4 ++ pushl %esp ++ CFI_ADJUST_CFA_OFFSET 4 ++ movzwl %sp, %esp ++ addw $4, (%esp) ++ /* copy the iret frame of 12 bytes */ ++ .rept 3 ++ pushl 16(%esp) ++ CFI_ADJUST_CFA_OFFSET 4 ++ .endr ++ pushl %eax ++ CFI_ADJUST_CFA_OFFSET 4 ++ SAVE_ALL ++ FIXUP_ESPFIX_STACK # %eax == %esp ++ CFI_ADJUST_CFA_OFFSET -20 # the frame has now moved ++ xorl %edx,%edx # zero error code ++ call do_nmi ++ RESTORE_REGS ++ lss 12+4(%esp), %esp # back to 16bit stack ++1: iret ++ CFI_ENDPROC ++.section __ex_table,"a" ++ .align 4 ++ .long 1b,iret_exc ++.previous ++#else ++ENTRY(nmi) ++ RING0_INT_FRAME ++ pushl %eax ++ CFI_ADJUST_CFA_OFFSET 4 ++ SAVE_ALL ++ xorl %edx,%edx # zero error code ++ movl %esp,%eax # pt_regs pointer ++ call do_nmi ++ orl $NMI_MASK, EFLAGS(%esp) ++ jmp restore_all ++ CFI_ENDPROC ++#endif ++ ++KPROBE_ENTRY(int3) ++ RING0_INT_FRAME ++ pushl $-1 # mark this as an int ++ CFI_ADJUST_CFA_OFFSET 4 ++ SAVE_ALL ++ xorl %edx,%edx # zero error code ++ movl %esp,%eax # pt_regs pointer ++ call do_int3 ++ jmp ret_from_exception ++ CFI_ENDPROC ++ .previous .text ++ ++ENTRY(overflow) ++ RING0_INT_FRAME ++ pushl $0 ++ CFI_ADJUST_CFA_OFFSET 4 ++ pushl $do_overflow ++ CFI_ADJUST_CFA_OFFSET 4 ++ jmp error_code ++ CFI_ENDPROC ++ ++ENTRY(bounds) ++ RING0_INT_FRAME ++ pushl $0 ++ CFI_ADJUST_CFA_OFFSET 4 ++ pushl $do_bounds ++ CFI_ADJUST_CFA_OFFSET 4 ++ jmp error_code ++ CFI_ENDPROC ++ ++ENTRY(invalid_op) ++ RING0_INT_FRAME ++ pushl $0 ++ CFI_ADJUST_CFA_OFFSET 4 ++ pushl $do_invalid_op ++ CFI_ADJUST_CFA_OFFSET 4 ++ jmp error_code ++ CFI_ENDPROC ++ ++ENTRY(coprocessor_segment_overrun) ++ RING0_INT_FRAME ++ pushl $0 ++ CFI_ADJUST_CFA_OFFSET 4 ++ pushl $do_coprocessor_segment_overrun ++ CFI_ADJUST_CFA_OFFSET 4 ++ jmp error_code ++ CFI_ENDPROC ++ ++ENTRY(invalid_TSS) ++ RING0_EC_FRAME ++ pushl $do_invalid_TSS ++ CFI_ADJUST_CFA_OFFSET 4 ++ jmp error_code ++ CFI_ENDPROC ++ ++ENTRY(segment_not_present) ++ RING0_EC_FRAME ++ pushl $do_segment_not_present ++ CFI_ADJUST_CFA_OFFSET 4 ++ jmp error_code ++ CFI_ENDPROC ++ ++ENTRY(stack_segment) ++ RING0_EC_FRAME ++ pushl $do_stack_segment ++ CFI_ADJUST_CFA_OFFSET 4 ++ jmp error_code ++ CFI_ENDPROC ++ ++KPROBE_ENTRY(general_protection) ++ RING0_EC_FRAME ++ pushl $do_general_protection ++ CFI_ADJUST_CFA_OFFSET 4 ++ jmp error_code ++ CFI_ENDPROC ++ .previous .text ++ ++ENTRY(alignment_check) ++ RING0_EC_FRAME ++ pushl $do_alignment_check ++ CFI_ADJUST_CFA_OFFSET 4 ++ jmp error_code ++ CFI_ENDPROC ++ ++KPROBE_ENTRY(page_fault) ++ RING0_EC_FRAME ++ pushl $do_page_fault ++ CFI_ADJUST_CFA_OFFSET 4 ++ jmp error_code ++ CFI_ENDPROC ++ .previous .text ++ ++#ifdef CONFIG_X86_MCE ++ENTRY(machine_check) ++ RING0_INT_FRAME ++ pushl $0 ++ CFI_ADJUST_CFA_OFFSET 4 ++ pushl machine_check_vector ++ CFI_ADJUST_CFA_OFFSET 4 ++ jmp error_code ++ CFI_ENDPROC ++#endif ++ ++#ifndef CONFIG_XEN ++ENTRY(spurious_interrupt_bug) ++ RING0_INT_FRAME ++ pushl $0 ++ CFI_ADJUST_CFA_OFFSET 4 ++ pushl $do_spurious_interrupt_bug ++ CFI_ADJUST_CFA_OFFSET 4 ++ jmp error_code ++ CFI_ENDPROC ++#endif /* !CONFIG_XEN */ ++ ++#ifdef CONFIG_STACK_UNWIND ++ENTRY(arch_unwind_init_running) ++ CFI_STARTPROC ++ movl 4(%esp), %edx ++ movl (%esp), %ecx ++ leal 4(%esp), %eax ++ movl %ebx, EBX(%edx) ++ xorl %ebx, %ebx ++ movl %ebx, ECX(%edx) ++ movl %ebx, EDX(%edx) ++ movl %esi, ESI(%edx) ++ movl %edi, EDI(%edx) ++ movl %ebp, EBP(%edx) ++ movl %ebx, EAX(%edx) ++ movl $__USER_DS, DS(%edx) ++ movl $__USER_DS, ES(%edx) ++ movl %ebx, ORIG_EAX(%edx) ++ movl %ecx, EIP(%edx) ++ movl 12(%esp), %ecx ++ movl $__KERNEL_CS, CS(%edx) ++ movl %ebx, EFLAGS(%edx) ++ movl %eax, OLDESP(%edx) ++ movl 8(%esp), %eax ++ movl %ecx, 8(%esp) ++ movl EBX(%edx), %ebx ++ movl $__KERNEL_DS, OLDSS(%edx) ++ jmpl *%eax ++ CFI_ENDPROC ++ENDPROC(arch_unwind_init_running) ++#endif ++ ++ENTRY(fixup_4gb_segment) ++ RING0_EC_FRAME ++ pushl $do_fixup_4gb_segment ++ CFI_ADJUST_CFA_OFFSET 4 ++ jmp error_code ++ CFI_ENDPROC ++ ++.section .rodata,"a" ++#include "syscall_table.S" ++ ++syscall_table_size=(.-sys_call_table) +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/arch/x86/kernel/fixup.c 2008-01-28 12:24:18.000000000 +0100 +@@ -0,0 +1,88 @@ ++/****************************************************************************** ++ * fixup.c ++ * ++ * Binary-rewriting of certain IA32 instructions, on notification by Xen. ++ * Used to avoid repeated slow emulation of common instructions used by the ++ * user-space TLS (Thread-Local Storage) libraries. ++ * ++ * **** NOTE **** ++ * Issues with the binary rewriting have caused it to be removed. Instead ++ * we rely on Xen's emulator to boot the kernel, and then print a banner ++ * message recommending that the user disables /lib/tls. ++ * ++ * Copyright (c) 2004, K A Fraser ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define DP(_f, _args...) printk(KERN_ALERT " " _f "\n" , ## _args ) ++ ++fastcall void do_fixup_4gb_segment(struct pt_regs *regs, long error_code) ++{ ++ static unsigned long printed = 0; ++ char info[100]; ++ int i; ++ ++ /* Ignore statically-linked init. */ ++ if (current->tgid == 1) ++ return; ++ ++ VOID(HYPERVISOR_vm_assist(VMASST_CMD_disable, ++ VMASST_TYPE_4gb_segments_notify)); ++ ++ if (test_and_set_bit(0, &printed)) ++ return; ++ ++ sprintf(info, "%s (pid=%d)", current->comm, current->tgid); ++ ++ DP(""); ++ DP("***************************************************************"); ++ DP("***************************************************************"); ++ DP("** WARNING: Currently emulating unsupported memory accesses **"); ++ DP("** in /lib/tls glibc libraries. The emulation is **"); ++ DP("** slow. To ensure full performance you should **"); ++ DP("** install a 'xen-friendly' (nosegneg) version of **"); ++ DP("** the library, or disable tls support by executing **"); ++ DP("** the following as root: **"); ++ DP("** mv /lib/tls /lib/tls.disabled **"); ++ DP("** Offending process: %-38.38s **", info); ++ DP("***************************************************************"); ++ DP("***************************************************************"); ++ DP(""); ++ ++ for (i = 5; i > 0; i--) { ++ touch_softlockup_watchdog(); ++ printk("Pausing... %d", i); ++ mdelay(1000); ++ printk("\b\b\b\b\b\b\b\b\b\b\b\b"); ++ } ++ ++ printk("Continuing...\n\n"); ++} ++ ++static int __init fixup_init(void) ++{ ++ WARN_ON(HYPERVISOR_vm_assist(VMASST_CMD_enable, ++ VMASST_TYPE_4gb_segments_notify)); ++ return 0; ++} ++__initcall(fixup_init); +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/arch/x86/kernel/head_32-xen.S 2007-06-12 13:12:48.000000000 +0200 +@@ -0,0 +1,207 @@ ++ ++ ++.text ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* ++ * References to members of the new_cpu_data structure. ++ */ ++ ++#define X86 new_cpu_data+CPUINFO_x86 ++#define X86_VENDOR new_cpu_data+CPUINFO_x86_vendor ++#define X86_MODEL new_cpu_data+CPUINFO_x86_model ++#define X86_MASK new_cpu_data+CPUINFO_x86_mask ++#define X86_HARD_MATH new_cpu_data+CPUINFO_hard_math ++#define X86_CPUID new_cpu_data+CPUINFO_cpuid_level ++#define X86_CAPABILITY new_cpu_data+CPUINFO_x86_capability ++#define X86_VENDOR_ID new_cpu_data+CPUINFO_x86_vendor_id ++ ++#define VIRT_ENTRY_OFFSET 0x0 ++.org VIRT_ENTRY_OFFSET ++ENTRY(startup_32) ++ movl %esi,xen_start_info ++ cld ++ ++ /* Set up the stack pointer */ ++ movl $(init_thread_union+THREAD_SIZE),%esp ++ ++ /* get vendor info */ ++ xorl %eax,%eax # call CPUID with 0 -> return vendor ID ++ XEN_CPUID ++ movl %eax,X86_CPUID # save CPUID level ++ movl %ebx,X86_VENDOR_ID # lo 4 chars ++ movl %edx,X86_VENDOR_ID+4 # next 4 chars ++ movl %ecx,X86_VENDOR_ID+8 # last 4 chars ++ ++ movl $1,%eax # Use the CPUID instruction to get CPU type ++ XEN_CPUID ++ movb %al,%cl # save reg for future use ++ andb $0x0f,%ah # mask processor family ++ movb %ah,X86 ++ andb $0xf0,%al # mask model ++ shrb $4,%al ++ movb %al,X86_MODEL ++ andb $0x0f,%cl # mask mask revision ++ movb %cl,X86_MASK ++ movl %edx,X86_CAPABILITY ++ ++ movb $1,X86_HARD_MATH ++ ++ xorl %eax,%eax # Clear FS/GS and LDT ++ movl %eax,%fs ++ movl %eax,%gs ++ cld # gcc2 wants the direction flag cleared at all times ++ ++ pushl %eax # fake return address ++ jmp start_kernel ++ ++#define HYPERCALL_PAGE_OFFSET 0x1000 ++.org HYPERCALL_PAGE_OFFSET ++ENTRY(hypercall_page) ++ CFI_STARTPROC ++.skip 0x1000 ++ CFI_ENDPROC ++ ++/* ++ * Real beginning of normal "text" segment ++ */ ++ENTRY(stext) ++ENTRY(_stext) ++ ++/* ++ * BSS section ++ */ ++.section ".bss.page_aligned","w" ++ENTRY(empty_zero_page) ++ .fill 4096,1,0 ++ ++/* ++ * This starts the data section. ++ */ ++.data ++ ++/* ++ * The Global Descriptor Table contains 28 quadwords, per-CPU. ++ */ ++ .align L1_CACHE_BYTES ++ENTRY(cpu_gdt_table) ++ .quad 0x0000000000000000 /* NULL descriptor */ ++ .quad 0x0000000000000000 /* 0x0b reserved */ ++ .quad 0x0000000000000000 /* 0x13 reserved */ ++ .quad 0x0000000000000000 /* 0x1b reserved */ ++ .quad 0x0000000000000000 /* 0x20 unused */ ++ .quad 0x0000000000000000 /* 0x28 unused */ ++ .quad 0x0000000000000000 /* 0x33 TLS entry 1 */ ++ .quad 0x0000000000000000 /* 0x3b TLS entry 2 */ ++ .quad 0x0000000000000000 /* 0x43 TLS entry 3 */ ++ .quad 0x0000000000000000 /* 0x4b reserved */ ++ .quad 0x0000000000000000 /* 0x53 reserved */ ++ .quad 0x0000000000000000 /* 0x5b reserved */ ++ ++ .quad 0x00cf9a000000ffff /* 0x60 kernel 4GB code at 0x00000000 */ ++ .quad 0x00cf92000000ffff /* 0x68 kernel 4GB data at 0x00000000 */ ++ .quad 0x00cffa000000ffff /* 0x73 user 4GB code at 0x00000000 */ ++ .quad 0x00cff2000000ffff /* 0x7b user 4GB data at 0x00000000 */ ++ ++ .quad 0x0000000000000000 /* 0x80 TSS descriptor */ ++ .quad 0x0000000000000000 /* 0x88 LDT descriptor */ ++ ++ /* ++ * Segments used for calling PnP BIOS have byte granularity. ++ * They code segments and data segments have fixed 64k limits, ++ * the transfer segment sizes are set at run time. ++ */ ++ .quad 0x0000000000000000 /* 0x90 32-bit code */ ++ .quad 0x0000000000000000 /* 0x98 16-bit code */ ++ .quad 0x0000000000000000 /* 0xa0 16-bit data */ ++ .quad 0x0000000000000000 /* 0xa8 16-bit data */ ++ .quad 0x0000000000000000 /* 0xb0 16-bit data */ ++ ++ /* ++ * The APM segments have byte granularity and their bases ++ * are set at run time. All have 64k limits. ++ */ ++ .quad 0x0000000000000000 /* 0xb8 APM CS code */ ++ .quad 0x0000000000000000 /* 0xc0 APM CS 16 code (16 bit) */ ++ .quad 0x0000000000000000 /* 0xc8 APM DS data */ ++ ++ .quad 0x0000000000000000 /* 0xd0 - ESPFIX 16-bit SS */ ++ .quad 0x0000000000000000 /* 0xd8 - unused */ ++ .quad 0x0000000000000000 /* 0xe0 - unused */ ++ .quad 0x0000000000000000 /* 0xe8 - unused */ ++ .quad 0x0000000000000000 /* 0xf0 - unused */ ++ .quad 0x0000000000000000 /* 0xf8 - GDT entry 31: double-fault TSS */ ++ ++#if CONFIG_XEN_COMPAT <= 0x030002 ++/* ++ * __xen_guest information ++ */ ++.macro utoa value ++ .if (\value) < 0 || (\value) >= 0x10 ++ utoa (((\value)>>4)&0x0fffffff) ++ .endif ++ .if ((\value) & 0xf) < 10 ++ .byte '0' + ((\value) & 0xf) ++ .else ++ .byte 'A' + ((\value) & 0xf) - 10 ++ .endif ++.endm ++ ++.section __xen_guest ++ .ascii "GUEST_OS=linux,GUEST_VER=2.6" ++ .ascii ",XEN_VER=xen-3.0" ++ .ascii ",VIRT_BASE=0x" ++ utoa __PAGE_OFFSET ++ .ascii ",ELF_PADDR_OFFSET=0x" ++ utoa __PAGE_OFFSET ++ .ascii ",VIRT_ENTRY=0x" ++ utoa (__PAGE_OFFSET + __PHYSICAL_START + VIRT_ENTRY_OFFSET) ++ .ascii ",HYPERCALL_PAGE=0x" ++ utoa ((__PHYSICAL_START+HYPERCALL_PAGE_OFFSET)>>PAGE_SHIFT) ++ .ascii ",FEATURES=writable_page_tables" ++ .ascii "|writable_descriptor_tables" ++ .ascii "|auto_translated_physmap" ++ .ascii "|pae_pgdir_above_4gb" ++ .ascii "|supervisor_mode_kernel" ++#ifdef CONFIG_X86_PAE ++ .ascii ",PAE=yes[extended-cr3]" ++#else ++ .ascii ",PAE=no" ++#endif ++ .ascii ",LOADER=generic" ++ .byte 0 ++#endif /* CONFIG_XEN_COMPAT <= 0x030002 */ ++ ++ ++ ELFNOTE(Xen, XEN_ELFNOTE_GUEST_OS, .asciz, "linux") ++ ELFNOTE(Xen, XEN_ELFNOTE_GUEST_VERSION, .asciz, "2.6") ++ ELFNOTE(Xen, XEN_ELFNOTE_XEN_VERSION, .asciz, "xen-3.0") ++ ELFNOTE(Xen, XEN_ELFNOTE_VIRT_BASE, .long, __PAGE_OFFSET) ++#if CONFIG_XEN_COMPAT <= 0x030002 ++ ELFNOTE(Xen, XEN_ELFNOTE_PADDR_OFFSET, .long, __PAGE_OFFSET) ++#else ++ ELFNOTE(Xen, XEN_ELFNOTE_PADDR_OFFSET, .long, 0) ++#endif ++ ELFNOTE(Xen, XEN_ELFNOTE_ENTRY, .long, startup_32) ++ ELFNOTE(Xen, XEN_ELFNOTE_HYPERCALL_PAGE, .long, hypercall_page) ++ ELFNOTE(Xen, XEN_ELFNOTE_HV_START_LOW, .long, HYPERVISOR_VIRT_START) ++ ELFNOTE(Xen, XEN_ELFNOTE_FEATURES, .asciz, "writable_page_tables|writable_descriptor_tables|auto_translated_physmap|pae_pgdir_above_4gb|supervisor_mode_kernel") ++#ifdef CONFIG_X86_PAE ++ ELFNOTE(Xen, XEN_ELFNOTE_PAE_MODE, .asciz, "yes") ++ ELFNOTE(Xen, XEN_ELFNOTE_L1_MFN_VALID, .quad, _PAGE_PRESENT,_PAGE_PRESENT) ++#else ++ ELFNOTE(Xen, XEN_ELFNOTE_PAE_MODE, .asciz, "no") ++ ELFNOTE(Xen, XEN_ELFNOTE_L1_MFN_VALID, .long, _PAGE_PRESENT,_PAGE_PRESENT) ++#endif ++ ELFNOTE(Xen, XEN_ELFNOTE_LOADER, .asciz, "generic") ++ ELFNOTE(Xen, XEN_ELFNOTE_SUSPEND_CANCEL, .long, 1) +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/arch/x86/kernel/io_apic_32-xen.c 2009-03-18 10:39:31.000000000 +0100 +@@ -0,0 +1,2786 @@ ++/* ++ * Intel IO-APIC support for multi-Pentium hosts. ++ * ++ * Copyright (C) 1997, 1998, 1999, 2000 Ingo Molnar, Hajnalka Szabo ++ * ++ * Many thanks to Stig Venaas for trying out countless experimental ++ * patches and reporting/debugging problems patiently! ++ * ++ * (c) 1999, Multiple IO-APIC support, developed by ++ * Ken-ichi Yaku and ++ * Hidemi Kishimoto , ++ * further tested and cleaned up by Zach Brown ++ * and Ingo Molnar ++ * ++ * Fixes ++ * Maciej W. Rozycki : Bits for genuine 82489DX APICs; ++ * thanks to Eric Gilmore ++ * and Rolf G. Tews ++ * for testing these extensively ++ * Paul Diefenbaugh : Added full ACPI support ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "io_ports.h" ++ ++#ifdef CONFIG_XEN ++ ++#include ++#include ++#include ++ ++/* Fake i8259 */ ++#define make_8259A_irq(_irq) (io_apic_irqs &= ~(1UL<<(_irq))) ++#define disable_8259A_irq(_irq) ((void)0) ++#define i8259A_irq_pending(_irq) (0) ++ ++unsigned long io_apic_irqs; ++ ++static inline unsigned int xen_io_apic_read(unsigned int apic, unsigned int reg) ++{ ++ struct physdev_apic apic_op; ++ int ret; ++ ++ apic_op.apic_physbase = mp_ioapics[apic].mpc_apicaddr; ++ apic_op.reg = reg; ++ ret = HYPERVISOR_physdev_op(PHYSDEVOP_apic_read, &apic_op); ++ if (ret) ++ return ret; ++ return apic_op.value; ++} ++ ++static inline void xen_io_apic_write(unsigned int apic, unsigned int reg, unsigned int value) ++{ ++ struct physdev_apic apic_op; ++ ++ apic_op.apic_physbase = mp_ioapics[apic].mpc_apicaddr; ++ apic_op.reg = reg; ++ apic_op.value = value; ++ WARN_ON(HYPERVISOR_physdev_op(PHYSDEVOP_apic_write, &apic_op)); ++} ++ ++#define io_apic_read(a,r) xen_io_apic_read(a,r) ++#define io_apic_write(a,r,v) xen_io_apic_write(a,r,v) ++ ++#endif /* CONFIG_XEN */ ++ ++int (*ioapic_renumber_irq)(int ioapic, int irq); ++atomic_t irq_mis_count; ++ ++#ifndef CONFIG_XEN ++/* Where if anywhere is the i8259 connect in external int mode */ ++static struct { int pin, apic; } ioapic_i8259 = { -1, -1 }; ++#endif ++ ++static DEFINE_SPINLOCK(ioapic_lock); ++static DEFINE_SPINLOCK(vector_lock); ++ ++int timer_over_8254 __initdata = 1; ++ ++/* ++ * Is the SiS APIC rmw bug present ? ++ * -1 = don't know, 0 = no, 1 = yes ++ */ ++int sis_apic_bug = -1; ++ ++/* ++ * # of IRQ routing registers ++ */ ++int nr_ioapic_registers[MAX_IO_APICS]; ++ ++int disable_timer_pin_1 __initdata; ++ ++/* ++ * Rough estimation of how many shared IRQs there are, can ++ * be changed anytime. ++ */ ++#define MAX_PLUS_SHARED_IRQS NR_IRQS ++#define PIN_MAP_SIZE (MAX_PLUS_SHARED_IRQS + NR_IRQS) ++ ++/* ++ * This is performance-critical, we want to do it O(1) ++ * ++ * the indexing order of this array favors 1:1 mappings ++ * between pins and IRQs. ++ */ ++ ++static struct irq_pin_list { ++ int apic, pin, next; ++} irq_2_pin[PIN_MAP_SIZE]; ++ ++int vector_irq[NR_VECTORS] __read_mostly = { [0 ... NR_VECTORS - 1] = -1}; ++#ifdef CONFIG_PCI_MSI ++#define vector_to_irq(vector) \ ++ (platform_legacy_irq(vector) ? vector : vector_irq[vector]) ++#else ++#define vector_to_irq(vector) (vector) ++#endif ++ ++/* ++ * The common case is 1:1 IRQ<->pin mappings. Sometimes there are ++ * shared ISA-space IRQs, so we have to support them. We are super ++ * fast in the common case, and fast for shared ISA-space IRQs. ++ */ ++static void add_pin_to_irq(unsigned int irq, int apic, int pin) ++{ ++ static int first_free_entry = NR_IRQS; ++ struct irq_pin_list *entry = irq_2_pin + irq; ++ ++ while (entry->next) ++ entry = irq_2_pin + entry->next; ++ ++ if (entry->pin != -1) { ++ entry->next = first_free_entry; ++ entry = irq_2_pin + entry->next; ++ if (++first_free_entry >= PIN_MAP_SIZE) ++ panic("io_apic.c: whoops"); ++ } ++ entry->apic = apic; ++ entry->pin = pin; ++} ++ ++#ifdef CONFIG_XEN ++#define clear_IO_APIC() ((void)0) ++#else ++/* ++ * Reroute an IRQ to a different pin. ++ */ ++static void __init replace_pin_at_irq(unsigned int irq, ++ int oldapic, int oldpin, ++ int newapic, int newpin) ++{ ++ struct irq_pin_list *entry = irq_2_pin + irq; ++ ++ while (1) { ++ if (entry->apic == oldapic && entry->pin == oldpin) { ++ entry->apic = newapic; ++ entry->pin = newpin; ++ } ++ if (!entry->next) ++ break; ++ entry = irq_2_pin + entry->next; ++ } ++} ++ ++static void __modify_IO_APIC_irq (unsigned int irq, unsigned long enable, unsigned long disable) ++{ ++ struct irq_pin_list *entry = irq_2_pin + irq; ++ unsigned int pin, reg; ++ ++ for (;;) { ++ pin = entry->pin; ++ if (pin == -1) ++ break; ++ reg = io_apic_read(entry->apic, 0x10 + pin*2); ++ reg &= ~disable; ++ reg |= enable; ++ io_apic_modify(entry->apic, 0x10 + pin*2, reg); ++ if (!entry->next) ++ break; ++ entry = irq_2_pin + entry->next; ++ } ++} ++ ++/* mask = 1 */ ++static void __mask_IO_APIC_irq (unsigned int irq) ++{ ++ __modify_IO_APIC_irq(irq, 0x00010000, 0); ++} ++ ++/* mask = 0 */ ++static void __unmask_IO_APIC_irq (unsigned int irq) ++{ ++ __modify_IO_APIC_irq(irq, 0, 0x00010000); ++} ++ ++/* mask = 1, trigger = 0 */ ++static void __mask_and_edge_IO_APIC_irq (unsigned int irq) ++{ ++ __modify_IO_APIC_irq(irq, 0x00010000, 0x00008000); ++} ++ ++/* mask = 0, trigger = 1 */ ++static void __unmask_and_level_IO_APIC_irq (unsigned int irq) ++{ ++ __modify_IO_APIC_irq(irq, 0x00008000, 0x00010000); ++} ++ ++static void mask_IO_APIC_irq (unsigned int irq) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&ioapic_lock, flags); ++ __mask_IO_APIC_irq(irq); ++ spin_unlock_irqrestore(&ioapic_lock, flags); ++} ++ ++static void unmask_IO_APIC_irq (unsigned int irq) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&ioapic_lock, flags); ++ __unmask_IO_APIC_irq(irq); ++ spin_unlock_irqrestore(&ioapic_lock, flags); ++} ++ ++static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin) ++{ ++ struct IO_APIC_route_entry entry; ++ unsigned long flags; ++ ++ /* Check delivery_mode to be sure we're not clearing an SMI pin */ ++ spin_lock_irqsave(&ioapic_lock, flags); ++ *(((int*)&entry) + 0) = io_apic_read(apic, 0x10 + 2 * pin); ++ *(((int*)&entry) + 1) = io_apic_read(apic, 0x11 + 2 * pin); ++ spin_unlock_irqrestore(&ioapic_lock, flags); ++ if (entry.delivery_mode == dest_SMI) ++ return; ++ ++ /* ++ * Disable it in the IO-APIC irq-routing table: ++ */ ++ memset(&entry, 0, sizeof(entry)); ++ entry.mask = 1; ++ spin_lock_irqsave(&ioapic_lock, flags); ++ io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry) + 0)); ++ io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry) + 1)); ++ spin_unlock_irqrestore(&ioapic_lock, flags); ++} ++ ++static void clear_IO_APIC (void) ++{ ++ int apic, pin; ++ ++ for (apic = 0; apic < nr_ioapics; apic++) ++ for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) ++ clear_IO_APIC_pin(apic, pin); ++} ++ ++#ifdef CONFIG_SMP ++static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t cpumask) ++{ ++ unsigned long flags; ++ int pin; ++ struct irq_pin_list *entry = irq_2_pin + irq; ++ unsigned int apicid_value; ++ cpumask_t tmp; ++ ++ cpus_and(tmp, cpumask, cpu_online_map); ++ if (cpus_empty(tmp)) ++ tmp = TARGET_CPUS; ++ ++ cpus_and(cpumask, tmp, CPU_MASK_ALL); ++ ++ apicid_value = cpu_mask_to_apicid(cpumask); ++ /* Prepare to do the io_apic_write */ ++ apicid_value = apicid_value << 24; ++ spin_lock_irqsave(&ioapic_lock, flags); ++ for (;;) { ++ pin = entry->pin; ++ if (pin == -1) ++ break; ++ io_apic_write(entry->apic, 0x10 + 1 + pin*2, apicid_value); ++ if (!entry->next) ++ break; ++ entry = irq_2_pin + entry->next; ++ } ++ set_irq_info(irq, cpumask); ++ spin_unlock_irqrestore(&ioapic_lock, flags); ++} ++ ++#if defined(CONFIG_IRQBALANCE) ++# include /* kernel_thread() */ ++# include /* kstat */ ++# include /* kmalloc() */ ++# include /* time_after() */ ++ ++#ifdef CONFIG_BALANCED_IRQ_DEBUG ++# define TDprintk(x...) do { printk("<%ld:%s:%d>: ", jiffies, __FILE__, __LINE__); printk(x); } while (0) ++# define Dprintk(x...) do { TDprintk(x); } while (0) ++# else ++# define TDprintk(x...) ++# define Dprintk(x...) ++# endif ++ ++#define IRQBALANCE_CHECK_ARCH -999 ++#define MAX_BALANCED_IRQ_INTERVAL (5*HZ) ++#define MIN_BALANCED_IRQ_INTERVAL (HZ/2) ++#define BALANCED_IRQ_MORE_DELTA (HZ/10) ++#define BALANCED_IRQ_LESS_DELTA (HZ) ++ ++static int irqbalance_disabled __read_mostly = IRQBALANCE_CHECK_ARCH; ++static int physical_balance __read_mostly; ++static long balanced_irq_interval __read_mostly = MAX_BALANCED_IRQ_INTERVAL; ++ ++static struct irq_cpu_info { ++ unsigned long * last_irq; ++ unsigned long * irq_delta; ++ unsigned long irq; ++} irq_cpu_data[NR_CPUS]; ++ ++#define CPU_IRQ(cpu) (irq_cpu_data[cpu].irq) ++#define LAST_CPU_IRQ(cpu,irq) (irq_cpu_data[cpu].last_irq[irq]) ++#define IRQ_DELTA(cpu,irq) (irq_cpu_data[cpu].irq_delta[irq]) ++ ++#define IDLE_ENOUGH(cpu,now) \ ++ (idle_cpu(cpu) && ((now) - per_cpu(irq_stat, (cpu)).idle_timestamp > 1)) ++ ++#define IRQ_ALLOWED(cpu, allowed_mask) cpu_isset(cpu, allowed_mask) ++ ++#define CPU_TO_PACKAGEINDEX(i) (first_cpu(cpu_sibling_map[i])) ++ ++static cpumask_t balance_irq_affinity[NR_IRQS] = { ++ [0 ... NR_IRQS-1] = CPU_MASK_ALL ++}; ++ ++void set_balance_irq_affinity(unsigned int irq, cpumask_t mask) ++{ ++ balance_irq_affinity[irq] = mask; ++} ++ ++static unsigned long move(int curr_cpu, cpumask_t allowed_mask, ++ unsigned long now, int direction) ++{ ++ int search_idle = 1; ++ int cpu = curr_cpu; ++ ++ goto inside; ++ ++ do { ++ if (unlikely(cpu == curr_cpu)) ++ search_idle = 0; ++inside: ++ if (direction == 1) { ++ cpu++; ++ if (cpu >= NR_CPUS) ++ cpu = 0; ++ } else { ++ cpu--; ++ if (cpu == -1) ++ cpu = NR_CPUS-1; ++ } ++ } while (!cpu_online(cpu) || !IRQ_ALLOWED(cpu,allowed_mask) || ++ (search_idle && !IDLE_ENOUGH(cpu,now))); ++ ++ return cpu; ++} ++ ++static inline void balance_irq(int cpu, int irq) ++{ ++ unsigned long now = jiffies; ++ cpumask_t allowed_mask; ++ unsigned int new_cpu; ++ ++ if (irqbalance_disabled) ++ return; ++ ++ cpus_and(allowed_mask, cpu_online_map, balance_irq_affinity[irq]); ++ new_cpu = move(cpu, allowed_mask, now, 1); ++ if (cpu != new_cpu) { ++ set_pending_irq(irq, cpumask_of_cpu(new_cpu)); ++ } ++} ++ ++static inline void rotate_irqs_among_cpus(unsigned long useful_load_threshold) ++{ ++ int i, j; ++ Dprintk("Rotating IRQs among CPUs.\n"); ++ for_each_online_cpu(i) { ++ for (j = 0; j < NR_IRQS; j++) { ++ if (!irq_desc[j].action) ++ continue; ++ /* Is it a significant load ? */ ++ if (IRQ_DELTA(CPU_TO_PACKAGEINDEX(i),j) < ++ useful_load_threshold) ++ continue; ++ balance_irq(i, j); ++ } ++ } ++ balanced_irq_interval = max((long)MIN_BALANCED_IRQ_INTERVAL, ++ balanced_irq_interval - BALANCED_IRQ_LESS_DELTA); ++ return; ++} ++ ++static void do_irq_balance(void) ++{ ++ int i, j; ++ unsigned long max_cpu_irq = 0, min_cpu_irq = (~0); ++ unsigned long move_this_load = 0; ++ int max_loaded = 0, min_loaded = 0; ++ int load; ++ unsigned long useful_load_threshold = balanced_irq_interval + 10; ++ int selected_irq; ++ int tmp_loaded, first_attempt = 1; ++ unsigned long tmp_cpu_irq; ++ unsigned long imbalance = 0; ++ cpumask_t allowed_mask, target_cpu_mask, tmp; ++ ++ for_each_possible_cpu(i) { ++ int package_index; ++ CPU_IRQ(i) = 0; ++ if (!cpu_online(i)) ++ continue; ++ package_index = CPU_TO_PACKAGEINDEX(i); ++ for (j = 0; j < NR_IRQS; j++) { ++ unsigned long value_now, delta; ++ /* Is this an active IRQ? */ ++ if (!irq_desc[j].action) ++ continue; ++ if ( package_index == i ) ++ IRQ_DELTA(package_index,j) = 0; ++ /* Determine the total count per processor per IRQ */ ++ value_now = (unsigned long) kstat_cpu(i).irqs[j]; ++ ++ /* Determine the activity per processor per IRQ */ ++ delta = value_now - LAST_CPU_IRQ(i,j); ++ ++ /* Update last_cpu_irq[][] for the next time */ ++ LAST_CPU_IRQ(i,j) = value_now; ++ ++ /* Ignore IRQs whose rate is less than the clock */ ++ if (delta < useful_load_threshold) ++ continue; ++ /* update the load for the processor or package total */ ++ IRQ_DELTA(package_index,j) += delta; ++ ++ /* Keep track of the higher numbered sibling as well */ ++ if (i != package_index) ++ CPU_IRQ(i) += delta; ++ /* ++ * We have sibling A and sibling B in the package ++ * ++ * cpu_irq[A] = load for cpu A + load for cpu B ++ * cpu_irq[B] = load for cpu B ++ */ ++ CPU_IRQ(package_index) += delta; ++ } ++ } ++ /* Find the least loaded processor package */ ++ for_each_online_cpu(i) { ++ if (i != CPU_TO_PACKAGEINDEX(i)) ++ continue; ++ if (min_cpu_irq > CPU_IRQ(i)) { ++ min_cpu_irq = CPU_IRQ(i); ++ min_loaded = i; ++ } ++ } ++ max_cpu_irq = ULONG_MAX; ++ ++tryanothercpu: ++ /* Look for heaviest loaded processor. ++ * We may come back to get the next heaviest loaded processor. ++ * Skip processors with trivial loads. ++ */ ++ tmp_cpu_irq = 0; ++ tmp_loaded = -1; ++ for_each_online_cpu(i) { ++ if (i != CPU_TO_PACKAGEINDEX(i)) ++ continue; ++ if (max_cpu_irq <= CPU_IRQ(i)) ++ continue; ++ if (tmp_cpu_irq < CPU_IRQ(i)) { ++ tmp_cpu_irq = CPU_IRQ(i); ++ tmp_loaded = i; ++ } ++ } ++ ++ if (tmp_loaded == -1) { ++ /* In the case of small number of heavy interrupt sources, ++ * loading some of the cpus too much. We use Ingo's original ++ * approach to rotate them around. ++ */ ++ if (!first_attempt && imbalance >= useful_load_threshold) { ++ rotate_irqs_among_cpus(useful_load_threshold); ++ return; ++ } ++ goto not_worth_the_effort; ++ } ++ ++ first_attempt = 0; /* heaviest search */ ++ max_cpu_irq = tmp_cpu_irq; /* load */ ++ max_loaded = tmp_loaded; /* processor */ ++ imbalance = (max_cpu_irq - min_cpu_irq) / 2; ++ ++ Dprintk("max_loaded cpu = %d\n", max_loaded); ++ Dprintk("min_loaded cpu = %d\n", min_loaded); ++ Dprintk("max_cpu_irq load = %ld\n", max_cpu_irq); ++ Dprintk("min_cpu_irq load = %ld\n", min_cpu_irq); ++ Dprintk("load imbalance = %lu\n", imbalance); ++ ++ /* if imbalance is less than approx 10% of max load, then ++ * observe diminishing returns action. - quit ++ */ ++ if (imbalance < (max_cpu_irq >> 3)) { ++ Dprintk("Imbalance too trivial\n"); ++ goto not_worth_the_effort; ++ } ++ ++tryanotherirq: ++ /* if we select an IRQ to move that can't go where we want, then ++ * see if there is another one to try. ++ */ ++ move_this_load = 0; ++ selected_irq = -1; ++ for (j = 0; j < NR_IRQS; j++) { ++ /* Is this an active IRQ? */ ++ if (!irq_desc[j].action) ++ continue; ++ if (imbalance <= IRQ_DELTA(max_loaded,j)) ++ continue; ++ /* Try to find the IRQ that is closest to the imbalance ++ * without going over. ++ */ ++ if (move_this_load < IRQ_DELTA(max_loaded,j)) { ++ move_this_load = IRQ_DELTA(max_loaded,j); ++ selected_irq = j; ++ } ++ } ++ if (selected_irq == -1) { ++ goto tryanothercpu; ++ } ++ ++ imbalance = move_this_load; ++ ++ /* For physical_balance case, we accumlated both load ++ * values in the one of the siblings cpu_irq[], ++ * to use the same code for physical and logical processors ++ * as much as possible. ++ * ++ * NOTE: the cpu_irq[] array holds the sum of the load for ++ * sibling A and sibling B in the slot for the lowest numbered ++ * sibling (A), _AND_ the load for sibling B in the slot for ++ * the higher numbered sibling. ++ * ++ * We seek the least loaded sibling by making the comparison ++ * (A+B)/2 vs B ++ */ ++ load = CPU_IRQ(min_loaded) >> 1; ++ for_each_cpu_mask(j, cpu_sibling_map[min_loaded]) { ++ if (load > CPU_IRQ(j)) { ++ /* This won't change cpu_sibling_map[min_loaded] */ ++ load = CPU_IRQ(j); ++ min_loaded = j; ++ } ++ } ++ ++ cpus_and(allowed_mask, ++ cpu_online_map, ++ balance_irq_affinity[selected_irq]); ++ target_cpu_mask = cpumask_of_cpu(min_loaded); ++ cpus_and(tmp, target_cpu_mask, allowed_mask); ++ ++ if (!cpus_empty(tmp)) { ++ ++ Dprintk("irq = %d moved to cpu = %d\n", ++ selected_irq, min_loaded); ++ /* mark for change destination */ ++ set_pending_irq(selected_irq, cpumask_of_cpu(min_loaded)); ++ ++ /* Since we made a change, come back sooner to ++ * check for more variation. ++ */ ++ balanced_irq_interval = max((long)MIN_BALANCED_IRQ_INTERVAL, ++ balanced_irq_interval - BALANCED_IRQ_LESS_DELTA); ++ return; ++ } ++ goto tryanotherirq; ++ ++not_worth_the_effort: ++ /* ++ * if we did not find an IRQ to move, then adjust the time interval ++ * upward ++ */ ++ balanced_irq_interval = min((long)MAX_BALANCED_IRQ_INTERVAL, ++ balanced_irq_interval + BALANCED_IRQ_MORE_DELTA); ++ Dprintk("IRQ worth rotating not found\n"); ++ return; ++} ++ ++static int balanced_irq(void *unused) ++{ ++ int i; ++ unsigned long prev_balance_time = jiffies; ++ long time_remaining = balanced_irq_interval; ++ ++ daemonize("kirqd"); ++ ++ /* push everything to CPU 0 to give us a starting point. */ ++ for (i = 0 ; i < NR_IRQS ; i++) { ++ irq_desc[i].pending_mask = cpumask_of_cpu(0); ++ set_pending_irq(i, cpumask_of_cpu(0)); ++ } ++ ++ for ( ; ; ) { ++ time_remaining = schedule_timeout_interruptible(time_remaining); ++ try_to_freeze(); ++ if (time_after(jiffies, ++ prev_balance_time+balanced_irq_interval)) { ++ preempt_disable(); ++ do_irq_balance(); ++ prev_balance_time = jiffies; ++ time_remaining = balanced_irq_interval; ++ preempt_enable(); ++ } ++ } ++ return 0; ++} ++ ++static int __init balanced_irq_init(void) ++{ ++ int i; ++ struct cpuinfo_x86 *c; ++ cpumask_t tmp; ++ ++ cpus_shift_right(tmp, cpu_online_map, 2); ++ c = &boot_cpu_data; ++ /* When not overwritten by the command line ask subarchitecture. */ ++ if (irqbalance_disabled == IRQBALANCE_CHECK_ARCH) ++ irqbalance_disabled = NO_BALANCE_IRQ; ++ if (irqbalance_disabled) ++ return 0; ++ ++ /* disable irqbalance completely if there is only one processor online */ ++ if (num_online_cpus() < 2) { ++ irqbalance_disabled = 1; ++ return 0; ++ } ++ /* ++ * Enable physical balance only if more than 1 physical processor ++ * is present ++ */ ++ if (smp_num_siblings > 1 && !cpus_empty(tmp)) ++ physical_balance = 1; ++ ++ for_each_online_cpu(i) { ++ irq_cpu_data[i].irq_delta = kmalloc(sizeof(unsigned long) * NR_IRQS, GFP_KERNEL); ++ irq_cpu_data[i].last_irq = kmalloc(sizeof(unsigned long) * NR_IRQS, GFP_KERNEL); ++ if (irq_cpu_data[i].irq_delta == NULL || irq_cpu_data[i].last_irq == NULL) { ++ printk(KERN_ERR "balanced_irq_init: out of memory"); ++ goto failed; ++ } ++ memset(irq_cpu_data[i].irq_delta,0,sizeof(unsigned long) * NR_IRQS); ++ memset(irq_cpu_data[i].last_irq,0,sizeof(unsigned long) * NR_IRQS); ++ } ++ ++ printk(KERN_INFO "Starting balanced_irq\n"); ++ if (kernel_thread(balanced_irq, NULL, CLONE_KERNEL) >= 0) ++ return 0; ++ else ++ printk(KERN_ERR "balanced_irq_init: failed to spawn balanced_irq"); ++failed: ++ for_each_possible_cpu(i) { ++ kfree(irq_cpu_data[i].irq_delta); ++ irq_cpu_data[i].irq_delta = NULL; ++ kfree(irq_cpu_data[i].last_irq); ++ irq_cpu_data[i].last_irq = NULL; ++ } ++ return 0; ++} ++ ++int __init irqbalance_disable(char *str) ++{ ++ irqbalance_disabled = 1; ++ return 1; ++} ++ ++__setup("noirqbalance", irqbalance_disable); ++ ++late_initcall(balanced_irq_init); ++#endif /* CONFIG_IRQBALANCE */ ++#endif /* CONFIG_SMP */ ++#endif ++ ++#ifndef CONFIG_SMP ++void fastcall send_IPI_self(int vector) ++{ ++#ifndef CONFIG_XEN ++ unsigned int cfg; ++ ++ /* ++ * Wait for idle. ++ */ ++ apic_wait_icr_idle(); ++ cfg = APIC_DM_FIXED | APIC_DEST_SELF | vector | APIC_DEST_LOGICAL; ++ /* ++ * Send the IPI. The write to APIC_ICR fires this off. ++ */ ++ apic_write_around(APIC_ICR, cfg); ++#endif ++} ++#endif /* !CONFIG_SMP */ ++ ++ ++/* ++ * support for broken MP BIOSs, enables hand-redirection of PIRQ0-7 to ++ * specific CPU-side IRQs. ++ */ ++ ++#define MAX_PIRQS 8 ++static int pirq_entries [MAX_PIRQS]; ++static int pirqs_enabled; ++int skip_ioapic_setup; ++ ++static int __init ioapic_setup(char *str) ++{ ++ skip_ioapic_setup = 1; ++ return 1; ++} ++ ++__setup("noapic", ioapic_setup); ++ ++static int __init ioapic_pirq_setup(char *str) ++{ ++ int i, max; ++ int ints[MAX_PIRQS+1]; ++ ++ get_options(str, ARRAY_SIZE(ints), ints); ++ ++ for (i = 0; i < MAX_PIRQS; i++) ++ pirq_entries[i] = -1; ++ ++ pirqs_enabled = 1; ++ apic_printk(APIC_VERBOSE, KERN_INFO ++ "PIRQ redirection, working around broken MP-BIOS.\n"); ++ max = MAX_PIRQS; ++ if (ints[0] < MAX_PIRQS) ++ max = ints[0]; ++ ++ for (i = 0; i < max; i++) { ++ apic_printk(APIC_VERBOSE, KERN_DEBUG ++ "... PIRQ%d -> IRQ %d\n", i, ints[i+1]); ++ /* ++ * PIRQs are mapped upside down, usually. ++ */ ++ pirq_entries[MAX_PIRQS-i-1] = ints[i+1]; ++ } ++ return 1; ++} ++ ++__setup("pirq=", ioapic_pirq_setup); ++ ++/* ++ * Find the IRQ entry number of a certain pin. ++ */ ++static int find_irq_entry(int apic, int pin, int type) ++{ ++ int i; ++ ++ for (i = 0; i < mp_irq_entries; i++) ++ if (mp_irqs[i].mpc_irqtype == type && ++ (mp_irqs[i].mpc_dstapic == mp_ioapics[apic].mpc_apicid || ++ mp_irqs[i].mpc_dstapic == MP_APIC_ALL) && ++ mp_irqs[i].mpc_dstirq == pin) ++ return i; ++ ++ return -1; ++} ++ ++#ifndef CONFIG_XEN ++/* ++ * Find the pin to which IRQ[irq] (ISA) is connected ++ */ ++static int __init find_isa_irq_pin(int irq, int type) ++{ ++ int i; ++ ++ for (i = 0; i < mp_irq_entries; i++) { ++ int lbus = mp_irqs[i].mpc_srcbus; ++ ++ if ((mp_bus_id_to_type[lbus] == MP_BUS_ISA || ++ mp_bus_id_to_type[lbus] == MP_BUS_EISA || ++ mp_bus_id_to_type[lbus] == MP_BUS_MCA || ++ mp_bus_id_to_type[lbus] == MP_BUS_NEC98 ++ ) && ++ (mp_irqs[i].mpc_irqtype == type) && ++ (mp_irqs[i].mpc_srcbusirq == irq)) ++ ++ return mp_irqs[i].mpc_dstirq; ++ } ++ return -1; ++} ++ ++static int __init find_isa_irq_apic(int irq, int type) ++{ ++ int i; ++ ++ for (i = 0; i < mp_irq_entries; i++) { ++ int lbus = mp_irqs[i].mpc_srcbus; ++ ++ if ((mp_bus_id_to_type[lbus] == MP_BUS_ISA || ++ mp_bus_id_to_type[lbus] == MP_BUS_EISA || ++ mp_bus_id_to_type[lbus] == MP_BUS_MCA || ++ mp_bus_id_to_type[lbus] == MP_BUS_NEC98 ++ ) && ++ (mp_irqs[i].mpc_irqtype == type) && ++ (mp_irqs[i].mpc_srcbusirq == irq)) ++ break; ++ } ++ if (i < mp_irq_entries) { ++ int apic; ++ for(apic = 0; apic < nr_ioapics; apic++) { ++ if (mp_ioapics[apic].mpc_apicid == mp_irqs[i].mpc_dstapic) ++ return apic; ++ } ++ } ++ ++ return -1; ++} ++#endif ++ ++/* ++ * Find a specific PCI IRQ entry. ++ * Not an __init, possibly needed by modules ++ */ ++static int pin_2_irq(int idx, int apic, int pin); ++ ++int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin) ++{ ++ int apic, i, best_guess = -1; ++ ++ apic_printk(APIC_DEBUG, "querying PCI -> IRQ mapping bus:%d, " ++ "slot:%d, pin:%d.\n", bus, slot, pin); ++ if (mp_bus_id_to_pci_bus[bus] == -1) { ++ printk(KERN_WARNING "PCI BIOS passed nonexistent PCI bus %d!\n", bus); ++ return -1; ++ } ++ for (i = 0; i < mp_irq_entries; i++) { ++ int lbus = mp_irqs[i].mpc_srcbus; ++ ++ for (apic = 0; apic < nr_ioapics; apic++) ++ if (mp_ioapics[apic].mpc_apicid == mp_irqs[i].mpc_dstapic || ++ mp_irqs[i].mpc_dstapic == MP_APIC_ALL) ++ break; ++ ++ if ((mp_bus_id_to_type[lbus] == MP_BUS_PCI) && ++ !mp_irqs[i].mpc_irqtype && ++ (bus == lbus) && ++ (slot == ((mp_irqs[i].mpc_srcbusirq >> 2) & 0x1f))) { ++ int irq = pin_2_irq(i,apic,mp_irqs[i].mpc_dstirq); ++ ++ if (!(apic || IO_APIC_IRQ(irq))) ++ continue; ++ ++ if (pin == (mp_irqs[i].mpc_srcbusirq & 3)) ++ return irq; ++ /* ++ * Use the first all-but-pin matching entry as a ++ * best-guess fuzzy result for broken mptables. ++ */ ++ if (best_guess < 0) ++ best_guess = irq; ++ } ++ } ++ return best_guess; ++} ++EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector); ++ ++/* ++ * This function currently is only a helper for the i386 smp boot process where ++ * we need to reprogram the ioredtbls to cater for the cpus which have come online ++ * so mask in all cases should simply be TARGET_CPUS ++ */ ++#ifdef CONFIG_SMP ++#ifndef CONFIG_XEN ++void __init setup_ioapic_dest(void) ++{ ++ int pin, ioapic, irq, irq_entry; ++ ++ if (skip_ioapic_setup == 1) ++ return; ++ ++ for (ioapic = 0; ioapic < nr_ioapics; ioapic++) { ++ for (pin = 0; pin < nr_ioapic_registers[ioapic]; pin++) { ++ irq_entry = find_irq_entry(ioapic, pin, mp_INT); ++ if (irq_entry == -1) ++ continue; ++ irq = pin_2_irq(irq_entry, ioapic, pin); ++ set_ioapic_affinity_irq(irq, TARGET_CPUS); ++ } ++ ++ } ++} ++#endif /* !CONFIG_XEN */ ++#endif ++ ++/* ++ * EISA Edge/Level control register, ELCR ++ */ ++static int EISA_ELCR(unsigned int irq) ++{ ++ if (irq < 16) { ++ unsigned int port = 0x4d0 + (irq >> 3); ++ return (inb(port) >> (irq & 7)) & 1; ++ } ++ apic_printk(APIC_VERBOSE, KERN_INFO ++ "Broken MPtable reports ISA irq %d\n", irq); ++ return 0; ++} ++ ++/* EISA interrupts are always polarity zero and can be edge or level ++ * trigger depending on the ELCR value. If an interrupt is listed as ++ * EISA conforming in the MP table, that means its trigger type must ++ * be read in from the ELCR */ ++ ++#define default_EISA_trigger(idx) (EISA_ELCR(mp_irqs[idx].mpc_srcbusirq)) ++#define default_EISA_polarity(idx) (0) ++ ++/* ISA interrupts are always polarity zero edge triggered, ++ * when listed as conforming in the MP table. */ ++ ++#define default_ISA_trigger(idx) (0) ++#define default_ISA_polarity(idx) (0) ++ ++/* PCI interrupts are always polarity one level triggered, ++ * when listed as conforming in the MP table. */ ++ ++#define default_PCI_trigger(idx) (1) ++#define default_PCI_polarity(idx) (1) ++ ++/* MCA interrupts are always polarity zero level triggered, ++ * when listed as conforming in the MP table. */ ++ ++#define default_MCA_trigger(idx) (1) ++#define default_MCA_polarity(idx) (0) ++ ++/* NEC98 interrupts are always polarity zero edge triggered, ++ * when listed as conforming in the MP table. */ ++ ++#define default_NEC98_trigger(idx) (0) ++#define default_NEC98_polarity(idx) (0) ++ ++static int __init MPBIOS_polarity(int idx) ++{ ++ int bus = mp_irqs[idx].mpc_srcbus; ++ int polarity; ++ ++ /* ++ * Determine IRQ line polarity (high active or low active): ++ */ ++ switch (mp_irqs[idx].mpc_irqflag & 3) ++ { ++ case 0: /* conforms, ie. bus-type dependent polarity */ ++ { ++ switch (mp_bus_id_to_type[bus]) ++ { ++ case MP_BUS_ISA: /* ISA pin */ ++ { ++ polarity = default_ISA_polarity(idx); ++ break; ++ } ++ case MP_BUS_EISA: /* EISA pin */ ++ { ++ polarity = default_EISA_polarity(idx); ++ break; ++ } ++ case MP_BUS_PCI: /* PCI pin */ ++ { ++ polarity = default_PCI_polarity(idx); ++ break; ++ } ++ case MP_BUS_MCA: /* MCA pin */ ++ { ++ polarity = default_MCA_polarity(idx); ++ break; ++ } ++ case MP_BUS_NEC98: /* NEC 98 pin */ ++ { ++ polarity = default_NEC98_polarity(idx); ++ break; ++ } ++ default: ++ { ++ printk(KERN_WARNING "broken BIOS!!\n"); ++ polarity = 1; ++ break; ++ } ++ } ++ break; ++ } ++ case 1: /* high active */ ++ { ++ polarity = 0; ++ break; ++ } ++ case 2: /* reserved */ ++ { ++ printk(KERN_WARNING "broken BIOS!!\n"); ++ polarity = 1; ++ break; ++ } ++ case 3: /* low active */ ++ { ++ polarity = 1; ++ break; ++ } ++ default: /* invalid */ ++ { ++ printk(KERN_WARNING "broken BIOS!!\n"); ++ polarity = 1; ++ break; ++ } ++ } ++ return polarity; ++} ++ ++static int MPBIOS_trigger(int idx) ++{ ++ int bus = mp_irqs[idx].mpc_srcbus; ++ int trigger; ++ ++ /* ++ * Determine IRQ trigger mode (edge or level sensitive): ++ */ ++ switch ((mp_irqs[idx].mpc_irqflag>>2) & 3) ++ { ++ case 0: /* conforms, ie. bus-type dependent */ ++ { ++ switch (mp_bus_id_to_type[bus]) ++ { ++ case MP_BUS_ISA: /* ISA pin */ ++ { ++ trigger = default_ISA_trigger(idx); ++ break; ++ } ++ case MP_BUS_EISA: /* EISA pin */ ++ { ++ trigger = default_EISA_trigger(idx); ++ break; ++ } ++ case MP_BUS_PCI: /* PCI pin */ ++ { ++ trigger = default_PCI_trigger(idx); ++ break; ++ } ++ case MP_BUS_MCA: /* MCA pin */ ++ { ++ trigger = default_MCA_trigger(idx); ++ break; ++ } ++ case MP_BUS_NEC98: /* NEC 98 pin */ ++ { ++ trigger = default_NEC98_trigger(idx); ++ break; ++ } ++ default: ++ { ++ printk(KERN_WARNING "broken BIOS!!\n"); ++ trigger = 1; ++ break; ++ } ++ } ++ break; ++ } ++ case 1: /* edge */ ++ { ++ trigger = 0; ++ break; ++ } ++ case 2: /* reserved */ ++ { ++ printk(KERN_WARNING "broken BIOS!!\n"); ++ trigger = 1; ++ break; ++ } ++ case 3: /* level */ ++ { ++ trigger = 1; ++ break; ++ } ++ default: /* invalid */ ++ { ++ printk(KERN_WARNING "broken BIOS!!\n"); ++ trigger = 0; ++ break; ++ } ++ } ++ return trigger; ++} ++ ++static inline int irq_polarity(int idx) ++{ ++ return MPBIOS_polarity(idx); ++} ++ ++static inline int irq_trigger(int idx) ++{ ++ return MPBIOS_trigger(idx); ++} ++ ++static int pin_2_irq(int idx, int apic, int pin) ++{ ++ int irq, i; ++ int bus = mp_irqs[idx].mpc_srcbus; ++ ++ /* ++ * Debugging check, we are in big trouble if this message pops up! ++ */ ++ if (mp_irqs[idx].mpc_dstirq != pin) ++ printk(KERN_ERR "broken BIOS or MPTABLE parser, ayiee!!\n"); ++ ++ switch (mp_bus_id_to_type[bus]) ++ { ++ case MP_BUS_ISA: /* ISA pin */ ++ case MP_BUS_EISA: ++ case MP_BUS_MCA: ++ case MP_BUS_NEC98: ++ { ++ irq = mp_irqs[idx].mpc_srcbusirq; ++ break; ++ } ++ case MP_BUS_PCI: /* PCI pin */ ++ { ++ /* ++ * PCI IRQs are mapped in order ++ */ ++ i = irq = 0; ++ while (i < apic) ++ irq += nr_ioapic_registers[i++]; ++ irq += pin; ++ ++ /* ++ * For MPS mode, so far only needed by ES7000 platform ++ */ ++ if (ioapic_renumber_irq) ++ irq = ioapic_renumber_irq(apic, irq); ++ ++ break; ++ } ++ default: ++ { ++ printk(KERN_ERR "unknown bus type %d.\n",bus); ++ irq = 0; ++ break; ++ } ++ } ++ ++ /* ++ * PCI IRQ command line redirection. Yes, limits are hardcoded. ++ */ ++ if ((pin >= 16) && (pin <= 23)) { ++ if (pirq_entries[pin-16] != -1) { ++ if (!pirq_entries[pin-16]) { ++ apic_printk(APIC_VERBOSE, KERN_DEBUG ++ "disabling PIRQ%d\n", pin-16); ++ } else { ++ irq = pirq_entries[pin-16]; ++ apic_printk(APIC_VERBOSE, KERN_DEBUG ++ "using PIRQ%d -> IRQ %d\n", ++ pin-16, irq); ++ } ++ } ++ } ++ return irq; ++} ++ ++static inline int IO_APIC_irq_trigger(int irq) ++{ ++ int apic, idx, pin; ++ ++ for (apic = 0; apic < nr_ioapics; apic++) { ++ for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) { ++ idx = find_irq_entry(apic,pin,mp_INT); ++ if ((idx != -1) && (irq == pin_2_irq(idx,apic,pin))) ++ return irq_trigger(idx); ++ } ++ } ++ /* ++ * nonexistent IRQs are edge default ++ */ ++ return 0; ++} ++ ++/* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */ ++u8 irq_vector[NR_IRQ_VECTORS] __read_mostly; /* = { FIRST_DEVICE_VECTOR , 0 }; */ ++ ++int assign_irq_vector(int irq) ++{ ++ unsigned long flags; ++ int vector; ++ struct physdev_irq irq_op; ++ ++ BUG_ON(irq != AUTO_ASSIGN && (unsigned)irq >= NR_IRQ_VECTORS); ++ ++ if (irq < PIRQ_BASE || irq - PIRQ_BASE >= NR_PIRQS) ++ return -EINVAL; ++ ++ spin_lock_irqsave(&vector_lock, flags); ++ ++ if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0) { ++ spin_unlock_irqrestore(&vector_lock, flags); ++ return IO_APIC_VECTOR(irq); ++ } ++ ++ irq_op.irq = irq; ++ if (HYPERVISOR_physdev_op(PHYSDEVOP_alloc_irq_vector, &irq_op)) { ++ spin_unlock_irqrestore(&vector_lock, flags); ++ return -ENOSPC; ++ } ++ ++ vector = irq_op.vector; ++ vector_irq[vector] = irq; ++ if (irq != AUTO_ASSIGN) ++ IO_APIC_VECTOR(irq) = vector; ++ ++ spin_unlock_irqrestore(&vector_lock, flags); ++ ++ return vector; ++} ++ ++#ifndef CONFIG_XEN ++static struct hw_interrupt_type ioapic_level_type; ++static struct hw_interrupt_type ioapic_edge_type; ++ ++#define IOAPIC_AUTO -1 ++#define IOAPIC_EDGE 0 ++#define IOAPIC_LEVEL 1 ++ ++static void ioapic_register_intr(int irq, int vector, unsigned long trigger) ++{ ++ unsigned idx; ++ ++ idx = use_pci_vector() && !platform_legacy_irq(irq) ? vector : irq; ++ ++ if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) || ++ trigger == IOAPIC_LEVEL) ++ irq_desc[idx].chip = &ioapic_level_type; ++ else ++ irq_desc[idx].chip = &ioapic_edge_type; ++ set_intr_gate(vector, interrupt[idx]); ++} ++#else ++#define ioapic_register_intr(irq, vector, trigger) evtchn_register_pirq(irq) ++#endif ++ ++static void __init setup_IO_APIC_irqs(void) ++{ ++ struct IO_APIC_route_entry entry; ++ int apic, pin, idx, irq, first_notcon = 1, vector; ++ unsigned long flags; ++ ++ apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n"); ++ ++ for (apic = 0; apic < nr_ioapics; apic++) { ++ for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) { ++ ++ /* ++ * add it to the IO-APIC irq-routing table: ++ */ ++ memset(&entry,0,sizeof(entry)); ++ ++ entry.delivery_mode = INT_DELIVERY_MODE; ++ entry.dest_mode = INT_DEST_MODE; ++ entry.mask = 0; /* enable IRQ */ ++ entry.dest.logical.logical_dest = ++ cpu_mask_to_apicid(TARGET_CPUS); ++ ++ idx = find_irq_entry(apic,pin,mp_INT); ++ if (idx == -1) { ++ if (first_notcon) { ++ apic_printk(APIC_VERBOSE, KERN_DEBUG ++ " IO-APIC (apicid-pin) %d-%d", ++ mp_ioapics[apic].mpc_apicid, ++ pin); ++ first_notcon = 0; ++ } else ++ apic_printk(APIC_VERBOSE, ", %d-%d", ++ mp_ioapics[apic].mpc_apicid, pin); ++ continue; ++ } ++ ++ entry.trigger = irq_trigger(idx); ++ entry.polarity = irq_polarity(idx); ++ ++ if (irq_trigger(idx)) { ++ entry.trigger = 1; ++ entry.mask = 1; ++ } ++ ++ irq = pin_2_irq(idx, apic, pin); ++ /* ++ * skip adding the timer int on secondary nodes, which causes ++ * a small but painful rift in the time-space continuum ++ */ ++ if (multi_timer_check(apic, irq)) ++ continue; ++ else ++ add_pin_to_irq(irq, apic, pin); ++ ++ if (/*!apic &&*/ !IO_APIC_IRQ(irq)) ++ continue; ++ ++ if (IO_APIC_IRQ(irq)) { ++ vector = assign_irq_vector(irq); ++ entry.vector = vector; ++ ioapic_register_intr(irq, vector, IOAPIC_AUTO); ++ ++ if (!apic && (irq < 16)) ++ disable_8259A_irq(irq); ++ } ++ spin_lock_irqsave(&ioapic_lock, flags); ++ io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1)); ++ io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0)); ++ set_native_irq_info(irq, TARGET_CPUS); ++ spin_unlock_irqrestore(&ioapic_lock, flags); ++ } ++ } ++ ++ if (!first_notcon) ++ apic_printk(APIC_VERBOSE, " not connected.\n"); ++} ++ ++/* ++ * Set up the 8259A-master output pin: ++ */ ++#ifndef CONFIG_XEN ++static void __init setup_ExtINT_IRQ0_pin(unsigned int apic, unsigned int pin, int vector) ++{ ++ struct IO_APIC_route_entry entry; ++ unsigned long flags; ++ ++ memset(&entry,0,sizeof(entry)); ++ ++ disable_8259A_irq(0); ++ ++ /* mask LVT0 */ ++ apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT); ++ ++ /* ++ * We use logical delivery to get the timer IRQ ++ * to the first CPU. ++ */ ++ entry.dest_mode = INT_DEST_MODE; ++ entry.mask = 0; /* unmask IRQ now */ ++ entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS); ++ entry.delivery_mode = INT_DELIVERY_MODE; ++ entry.polarity = 0; ++ entry.trigger = 0; ++ entry.vector = vector; ++ ++ /* ++ * The timer IRQ doesn't have to know that behind the ++ * scene we have a 8259A-master in AEOI mode ... ++ */ ++ irq_desc[0].chip = &ioapic_edge_type; ++ ++ /* ++ * Add it to the IO-APIC irq-routing table: ++ */ ++ spin_lock_irqsave(&ioapic_lock, flags); ++ io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1)); ++ io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0)); ++ spin_unlock_irqrestore(&ioapic_lock, flags); ++ ++ enable_8259A_irq(0); ++} ++ ++static inline void UNEXPECTED_IO_APIC(void) ++{ ++} ++ ++void __init print_IO_APIC(void) ++{ ++ int apic, i; ++ union IO_APIC_reg_00 reg_00; ++ union IO_APIC_reg_01 reg_01; ++ union IO_APIC_reg_02 reg_02; ++ union IO_APIC_reg_03 reg_03; ++ unsigned long flags; ++ ++ if (apic_verbosity == APIC_QUIET) ++ return; ++ ++ printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries); ++ for (i = 0; i < nr_ioapics; i++) ++ printk(KERN_DEBUG "number of IO-APIC #%d registers: %d.\n", ++ mp_ioapics[i].mpc_apicid, nr_ioapic_registers[i]); ++ ++ /* ++ * We are a bit conservative about what we expect. We have to ++ * know about every hardware change ASAP. ++ */ ++ printk(KERN_INFO "testing the IO APIC.......................\n"); ++ ++ for (apic = 0; apic < nr_ioapics; apic++) { ++ ++ spin_lock_irqsave(&ioapic_lock, flags); ++ reg_00.raw = io_apic_read(apic, 0); ++ reg_01.raw = io_apic_read(apic, 1); ++ if (reg_01.bits.version >= 0x10) ++ reg_02.raw = io_apic_read(apic, 2); ++ if (reg_01.bits.version >= 0x20) ++ reg_03.raw = io_apic_read(apic, 3); ++ spin_unlock_irqrestore(&ioapic_lock, flags); ++ ++ printk(KERN_DEBUG "IO APIC #%d......\n", mp_ioapics[apic].mpc_apicid); ++ printk(KERN_DEBUG ".... register #00: %08X\n", reg_00.raw); ++ printk(KERN_DEBUG "....... : physical APIC id: %02X\n", reg_00.bits.ID); ++ printk(KERN_DEBUG "....... : Delivery Type: %X\n", reg_00.bits.delivery_type); ++ printk(KERN_DEBUG "....... : LTS : %X\n", reg_00.bits.LTS); ++ if (reg_00.bits.ID >= get_physical_broadcast()) ++ UNEXPECTED_IO_APIC(); ++ if (reg_00.bits.__reserved_1 || reg_00.bits.__reserved_2) ++ UNEXPECTED_IO_APIC(); ++ ++ printk(KERN_DEBUG ".... register #01: %08X\n", reg_01.raw); ++ printk(KERN_DEBUG "....... : max redirection entries: %04X\n", reg_01.bits.entries); ++ if ( (reg_01.bits.entries != 0x0f) && /* older (Neptune) boards */ ++ (reg_01.bits.entries != 0x17) && /* typical ISA+PCI boards */ ++ (reg_01.bits.entries != 0x1b) && /* Compaq Proliant boards */ ++ (reg_01.bits.entries != 0x1f) && /* dual Xeon boards */ ++ (reg_01.bits.entries != 0x22) && /* bigger Xeon boards */ ++ (reg_01.bits.entries != 0x2E) && ++ (reg_01.bits.entries != 0x3F) ++ ) ++ UNEXPECTED_IO_APIC(); ++ ++ printk(KERN_DEBUG "....... : PRQ implemented: %X\n", reg_01.bits.PRQ); ++ printk(KERN_DEBUG "....... : IO APIC version: %04X\n", reg_01.bits.version); ++ if ( (reg_01.bits.version != 0x01) && /* 82489DX IO-APICs */ ++ (reg_01.bits.version != 0x10) && /* oldest IO-APICs */ ++ (reg_01.bits.version != 0x11) && /* Pentium/Pro IO-APICs */ ++ (reg_01.bits.version != 0x13) && /* Xeon IO-APICs */ ++ (reg_01.bits.version != 0x20) /* Intel P64H (82806 AA) */ ++ ) ++ UNEXPECTED_IO_APIC(); ++ if (reg_01.bits.__reserved_1 || reg_01.bits.__reserved_2) ++ UNEXPECTED_IO_APIC(); ++ ++ /* ++ * Some Intel chipsets with IO APIC VERSION of 0x1? don't have reg_02, ++ * but the value of reg_02 is read as the previous read register ++ * value, so ignore it if reg_02 == reg_01. ++ */ ++ if (reg_01.bits.version >= 0x10 && reg_02.raw != reg_01.raw) { ++ printk(KERN_DEBUG ".... register #02: %08X\n", reg_02.raw); ++ printk(KERN_DEBUG "....... : arbitration: %02X\n", reg_02.bits.arbitration); ++ if (reg_02.bits.__reserved_1 || reg_02.bits.__reserved_2) ++ UNEXPECTED_IO_APIC(); ++ } ++ ++ /* ++ * Some Intel chipsets with IO APIC VERSION of 0x2? don't have reg_02 ++ * or reg_03, but the value of reg_0[23] is read as the previous read ++ * register value, so ignore it if reg_03 == reg_0[12]. ++ */ ++ if (reg_01.bits.version >= 0x20 && reg_03.raw != reg_02.raw && ++ reg_03.raw != reg_01.raw) { ++ printk(KERN_DEBUG ".... register #03: %08X\n", reg_03.raw); ++ printk(KERN_DEBUG "....... : Boot DT : %X\n", reg_03.bits.boot_DT); ++ if (reg_03.bits.__reserved_1) ++ UNEXPECTED_IO_APIC(); ++ } ++ ++ printk(KERN_DEBUG ".... IRQ redirection table:\n"); ++ ++ printk(KERN_DEBUG " NR Log Phy Mask Trig IRR Pol" ++ " Stat Dest Deli Vect: \n"); ++ ++ for (i = 0; i <= reg_01.bits.entries; i++) { ++ struct IO_APIC_route_entry entry; ++ ++ spin_lock_irqsave(&ioapic_lock, flags); ++ *(((int *)&entry)+0) = io_apic_read(apic, 0x10+i*2); ++ *(((int *)&entry)+1) = io_apic_read(apic, 0x11+i*2); ++ spin_unlock_irqrestore(&ioapic_lock, flags); ++ ++ printk(KERN_DEBUG " %02x %03X %02X ", ++ i, ++ entry.dest.logical.logical_dest, ++ entry.dest.physical.physical_dest ++ ); ++ ++ printk("%1d %1d %1d %1d %1d %1d %1d %02X\n", ++ entry.mask, ++ entry.trigger, ++ entry.irr, ++ entry.polarity, ++ entry.delivery_status, ++ entry.dest_mode, ++ entry.delivery_mode, ++ entry.vector ++ ); ++ } ++ } ++ if (use_pci_vector()) ++ printk(KERN_INFO "Using vector-based indexing\n"); ++ printk(KERN_DEBUG "IRQ to pin mappings:\n"); ++ for (i = 0; i < NR_IRQS; i++) { ++ struct irq_pin_list *entry = irq_2_pin + i; ++ if (entry->pin < 0) ++ continue; ++ if (use_pci_vector() && !platform_legacy_irq(i)) ++ printk(KERN_DEBUG "IRQ%d ", IO_APIC_VECTOR(i)); ++ else ++ printk(KERN_DEBUG "IRQ%d ", i); ++ for (;;) { ++ printk("-> %d:%d", entry->apic, entry->pin); ++ if (!entry->next) ++ break; ++ entry = irq_2_pin + entry->next; ++ } ++ printk("\n"); ++ } ++ ++ printk(KERN_INFO ".................................... done.\n"); ++ ++ return; ++} ++ ++static void print_APIC_bitfield (int base) ++{ ++ unsigned int v; ++ int i, j; ++ ++ if (apic_verbosity == APIC_QUIET) ++ return; ++ ++ printk(KERN_DEBUG "0123456789abcdef0123456789abcdef\n" KERN_DEBUG); ++ for (i = 0; i < 8; i++) { ++ v = apic_read(base + i*0x10); ++ for (j = 0; j < 32; j++) { ++ if (v & (1< 3) /* Due to the Pentium erratum 3AP. */ ++ apic_write(APIC_ESR, 0); ++ v = apic_read(APIC_ESR); ++ printk(KERN_DEBUG "... APIC ESR: %08x\n", v); ++ } ++ ++ v = apic_read(APIC_ICR); ++ printk(KERN_DEBUG "... APIC ICR: %08x\n", v); ++ v = apic_read(APIC_ICR2); ++ printk(KERN_DEBUG "... APIC ICR2: %08x\n", v); ++ ++ v = apic_read(APIC_LVTT); ++ printk(KERN_DEBUG "... APIC LVTT: %08x\n", v); ++ ++ if (maxlvt > 3) { /* PC is LVT#4. */ ++ v = apic_read(APIC_LVTPC); ++ printk(KERN_DEBUG "... APIC LVTPC: %08x\n", v); ++ } ++ v = apic_read(APIC_LVT0); ++ printk(KERN_DEBUG "... APIC LVT0: %08x\n", v); ++ v = apic_read(APIC_LVT1); ++ printk(KERN_DEBUG "... APIC LVT1: %08x\n", v); ++ ++ if (maxlvt > 2) { /* ERR is LVT#3. */ ++ v = apic_read(APIC_LVTERR); ++ printk(KERN_DEBUG "... APIC LVTERR: %08x\n", v); ++ } ++ ++ v = apic_read(APIC_TMICT); ++ printk(KERN_DEBUG "... APIC TMICT: %08x\n", v); ++ v = apic_read(APIC_TMCCT); ++ printk(KERN_DEBUG "... APIC TMCCT: %08x\n", v); ++ v = apic_read(APIC_TDCR); ++ printk(KERN_DEBUG "... APIC TDCR: %08x\n", v); ++ printk("\n"); ++} ++ ++void print_all_local_APICs (void) ++{ ++ on_each_cpu(print_local_APIC, NULL, 1, 1); ++} ++ ++void /*__init*/ print_PIC(void) ++{ ++ unsigned int v; ++ unsigned long flags; ++ ++ if (apic_verbosity == APIC_QUIET) ++ return; ++ ++ printk(KERN_DEBUG "\nprinting PIC contents\n"); ++ ++ spin_lock_irqsave(&i8259A_lock, flags); ++ ++ v = inb(0xa1) << 8 | inb(0x21); ++ printk(KERN_DEBUG "... PIC IMR: %04x\n", v); ++ ++ v = inb(0xa0) << 8 | inb(0x20); ++ printk(KERN_DEBUG "... PIC IRR: %04x\n", v); ++ ++ outb(0x0b,0xa0); ++ outb(0x0b,0x20); ++ v = inb(0xa0) << 8 | inb(0x20); ++ outb(0x0a,0xa0); ++ outb(0x0a,0x20); ++ ++ spin_unlock_irqrestore(&i8259A_lock, flags); ++ ++ printk(KERN_DEBUG "... PIC ISR: %04x\n", v); ++ ++ v = inb(0x4d1) << 8 | inb(0x4d0); ++ printk(KERN_DEBUG "... PIC ELCR: %04x\n", v); ++} ++#endif /* !CONFIG_XEN */ ++ ++static void __init enable_IO_APIC(void) ++{ ++ union IO_APIC_reg_01 reg_01; ++#ifndef CONFIG_XEN ++ int i8259_apic, i8259_pin; ++#endif ++ int i, apic; ++ unsigned long flags; ++ ++ for (i = 0; i < PIN_MAP_SIZE; i++) { ++ irq_2_pin[i].pin = -1; ++ irq_2_pin[i].next = 0; ++ } ++ if (!pirqs_enabled) ++ for (i = 0; i < MAX_PIRQS; i++) ++ pirq_entries[i] = -1; ++ ++ /* ++ * The number of IO-APIC IRQ registers (== #pins): ++ */ ++ for (apic = 0; apic < nr_ioapics; apic++) { ++ spin_lock_irqsave(&ioapic_lock, flags); ++ reg_01.raw = io_apic_read(apic, 1); ++ spin_unlock_irqrestore(&ioapic_lock, flags); ++ nr_ioapic_registers[apic] = reg_01.bits.entries+1; ++ } ++#ifndef CONFIG_XEN ++ for(apic = 0; apic < nr_ioapics; apic++) { ++ int pin; ++ /* See if any of the pins is in ExtINT mode */ ++ for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) { ++ struct IO_APIC_route_entry entry; ++ spin_lock_irqsave(&ioapic_lock, flags); ++ *(((int *)&entry) + 0) = io_apic_read(apic, 0x10 + 2 * pin); ++ *(((int *)&entry) + 1) = io_apic_read(apic, 0x11 + 2 * pin); ++ spin_unlock_irqrestore(&ioapic_lock, flags); ++ ++ ++ /* If the interrupt line is enabled and in ExtInt mode ++ * I have found the pin where the i8259 is connected. ++ */ ++ if ((entry.mask == 0) && (entry.delivery_mode == dest_ExtINT)) { ++ ioapic_i8259.apic = apic; ++ ioapic_i8259.pin = pin; ++ goto found_i8259; ++ } ++ } ++ } ++ found_i8259: ++ /* Look to see what if the MP table has reported the ExtINT */ ++ /* If we could not find the appropriate pin by looking at the ioapic ++ * the i8259 probably is not connected the ioapic but give the ++ * mptable a chance anyway. ++ */ ++ i8259_pin = find_isa_irq_pin(0, mp_ExtINT); ++ i8259_apic = find_isa_irq_apic(0, mp_ExtINT); ++ /* Trust the MP table if nothing is setup in the hardware */ ++ if ((ioapic_i8259.pin == -1) && (i8259_pin >= 0)) { ++ printk(KERN_WARNING "ExtINT not setup in hardware but reported by MP table\n"); ++ ioapic_i8259.pin = i8259_pin; ++ ioapic_i8259.apic = i8259_apic; ++ } ++ /* Complain if the MP table and the hardware disagree */ ++ if (((ioapic_i8259.apic != i8259_apic) || (ioapic_i8259.pin != i8259_pin)) && ++ (i8259_pin >= 0) && (ioapic_i8259.pin >= 0)) ++ { ++ printk(KERN_WARNING "ExtINT in hardware and MP table differ\n"); ++ } ++#endif ++ ++ /* ++ * Do not trust the IO-APIC being empty at bootup ++ */ ++ clear_IO_APIC(); ++} ++ ++/* ++ * Not an __init, needed by the reboot code ++ */ ++void disable_IO_APIC(void) ++{ ++ /* ++ * Clear the IO-APIC before rebooting: ++ */ ++ clear_IO_APIC(); ++ ++#ifndef CONFIG_XEN ++ /* ++ * If the i8259 is routed through an IOAPIC ++ * Put that IOAPIC in virtual wire mode ++ * so legacy interrupts can be delivered. ++ */ ++ if (ioapic_i8259.pin != -1) { ++ struct IO_APIC_route_entry entry; ++ unsigned long flags; ++ ++ memset(&entry, 0, sizeof(entry)); ++ entry.mask = 0; /* Enabled */ ++ entry.trigger = 0; /* Edge */ ++ entry.irr = 0; ++ entry.polarity = 0; /* High */ ++ entry.delivery_status = 0; ++ entry.dest_mode = 0; /* Physical */ ++ entry.delivery_mode = dest_ExtINT; /* ExtInt */ ++ entry.vector = 0; ++ entry.dest.physical.physical_dest = ++ GET_APIC_ID(apic_read(APIC_ID)); ++ ++ /* ++ * Add it to the IO-APIC irq-routing table: ++ */ ++ spin_lock_irqsave(&ioapic_lock, flags); ++ io_apic_write(ioapic_i8259.apic, 0x11+2*ioapic_i8259.pin, ++ *(((int *)&entry)+1)); ++ io_apic_write(ioapic_i8259.apic, 0x10+2*ioapic_i8259.pin, ++ *(((int *)&entry)+0)); ++ spin_unlock_irqrestore(&ioapic_lock, flags); ++ } ++ disconnect_bsp_APIC(ioapic_i8259.pin != -1); ++#endif ++} ++ ++/* ++ * function to set the IO-APIC physical IDs based on the ++ * values stored in the MPC table. ++ * ++ * by Matt Domsch Tue Dec 21 12:25:05 CST 1999 ++ */ ++ ++#if !defined(CONFIG_XEN) && !defined(CONFIG_X86_NUMAQ) ++static void __init setup_ioapic_ids_from_mpc(void) ++{ ++ union IO_APIC_reg_00 reg_00; ++ physid_mask_t phys_id_present_map; ++ int apic; ++ int i; ++ unsigned char old_id; ++ unsigned long flags; ++ ++ /* ++ * Don't check I/O APIC IDs for xAPIC systems. They have ++ * no meaning without the serial APIC bus. ++ */ ++ if (!(boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) ++ || APIC_XAPIC(apic_version[boot_cpu_physical_apicid])) ++ return; ++ /* ++ * This is broken; anything with a real cpu count has to ++ * circumvent this idiocy regardless. ++ */ ++ phys_id_present_map = ioapic_phys_id_map(phys_cpu_present_map); ++ ++ /* ++ * Set the IOAPIC ID to the value stored in the MPC table. ++ */ ++ for (apic = 0; apic < nr_ioapics; apic++) { ++ ++ /* Read the register 0 value */ ++ spin_lock_irqsave(&ioapic_lock, flags); ++ reg_00.raw = io_apic_read(apic, 0); ++ spin_unlock_irqrestore(&ioapic_lock, flags); ++ ++ old_id = mp_ioapics[apic].mpc_apicid; ++ ++ if (mp_ioapics[apic].mpc_apicid >= get_physical_broadcast()) { ++ printk(KERN_ERR "BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n", ++ apic, mp_ioapics[apic].mpc_apicid); ++ printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n", ++ reg_00.bits.ID); ++ mp_ioapics[apic].mpc_apicid = reg_00.bits.ID; ++ } ++ ++ /* ++ * Sanity check, is the ID really free? Every APIC in a ++ * system must have a unique ID or we get lots of nice ++ * 'stuck on smp_invalidate_needed IPI wait' messages. ++ */ ++ if (check_apicid_used(phys_id_present_map, ++ mp_ioapics[apic].mpc_apicid)) { ++ printk(KERN_ERR "BIOS bug, IO-APIC#%d ID %d is already used!...\n", ++ apic, mp_ioapics[apic].mpc_apicid); ++ for (i = 0; i < get_physical_broadcast(); i++) ++ if (!physid_isset(i, phys_id_present_map)) ++ break; ++ if (i >= get_physical_broadcast()) ++ panic("Max APIC ID exceeded!\n"); ++ printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n", ++ i); ++ physid_set(i, phys_id_present_map); ++ mp_ioapics[apic].mpc_apicid = i; ++ } else { ++ physid_mask_t tmp; ++ tmp = apicid_to_cpu_present(mp_ioapics[apic].mpc_apicid); ++ apic_printk(APIC_VERBOSE, "Setting %d in the " ++ "phys_id_present_map\n", ++ mp_ioapics[apic].mpc_apicid); ++ physids_or(phys_id_present_map, phys_id_present_map, tmp); ++ } ++ ++ ++ /* ++ * We need to adjust the IRQ routing table ++ * if the ID changed. ++ */ ++ if (old_id != mp_ioapics[apic].mpc_apicid) ++ for (i = 0; i < mp_irq_entries; i++) ++ if (mp_irqs[i].mpc_dstapic == old_id) ++ mp_irqs[i].mpc_dstapic ++ = mp_ioapics[apic].mpc_apicid; ++ ++ /* ++ * Read the right value from the MPC table and ++ * write it into the ID register. ++ */ ++ apic_printk(APIC_VERBOSE, KERN_INFO ++ "...changing IO-APIC physical APIC ID to %d ...", ++ mp_ioapics[apic].mpc_apicid); ++ ++ reg_00.bits.ID = mp_ioapics[apic].mpc_apicid; ++ spin_lock_irqsave(&ioapic_lock, flags); ++ io_apic_write(apic, 0, reg_00.raw); ++ spin_unlock_irqrestore(&ioapic_lock, flags); ++ ++ /* ++ * Sanity check ++ */ ++ spin_lock_irqsave(&ioapic_lock, flags); ++ reg_00.raw = io_apic_read(apic, 0); ++ spin_unlock_irqrestore(&ioapic_lock, flags); ++ if (reg_00.bits.ID != mp_ioapics[apic].mpc_apicid) ++ printk("could not set ID!\n"); ++ else ++ apic_printk(APIC_VERBOSE, " ok.\n"); ++ } ++} ++#else ++static void __init setup_ioapic_ids_from_mpc(void) { } ++#endif ++ ++#ifndef CONFIG_XEN ++/* ++ * There is a nasty bug in some older SMP boards, their mptable lies ++ * about the timer IRQ. We do the following to work around the situation: ++ * ++ * - timer IRQ defaults to IO-APIC IRQ ++ * - if this function detects that timer IRQs are defunct, then we fall ++ * back to ISA timer IRQs ++ */ ++static int __init timer_irq_works(void) ++{ ++ unsigned long t1 = jiffies; ++ ++ local_irq_enable(); ++ /* Let ten ticks pass... */ ++ mdelay((10 * 1000) / HZ); ++ ++ /* ++ * Expect a few ticks at least, to be sure some possible ++ * glue logic does not lock up after one or two first ++ * ticks in a non-ExtINT mode. Also the local APIC ++ * might have cached one ExtINT interrupt. Finally, at ++ * least one tick may be lost due to delays. ++ */ ++ if (jiffies - t1 > 4) ++ return 1; ++ ++ return 0; ++} ++ ++/* ++ * In the SMP+IOAPIC case it might happen that there are an unspecified ++ * number of pending IRQ events unhandled. These cases are very rare, ++ * so we 'resend' these IRQs via IPIs, to the same CPU. It's much ++ * better to do it this way as thus we do not have to be aware of ++ * 'pending' interrupts in the IRQ path, except at this point. ++ */ ++/* ++ * Edge triggered needs to resend any interrupt ++ * that was delayed but this is now handled in the device ++ * independent code. ++ */ ++ ++/* ++ * Starting up a edge-triggered IO-APIC interrupt is ++ * nasty - we need to make sure that we get the edge. ++ * If it is already asserted for some reason, we need ++ * return 1 to indicate that is was pending. ++ * ++ * This is not complete - we should be able to fake ++ * an edge even if it isn't on the 8259A... ++ */ ++static unsigned int startup_edge_ioapic_irq(unsigned int irq) ++{ ++ int was_pending = 0; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&ioapic_lock, flags); ++ if (irq < 16) { ++ disable_8259A_irq(irq); ++ if (i8259A_irq_pending(irq)) ++ was_pending = 1; ++ } ++ __unmask_IO_APIC_irq(irq); ++ spin_unlock_irqrestore(&ioapic_lock, flags); ++ ++ return was_pending; ++} ++ ++/* ++ * Once we have recorded IRQ_PENDING already, we can mask the ++ * interrupt for real. This prevents IRQ storms from unhandled ++ * devices. ++ */ ++static void ack_edge_ioapic_irq(unsigned int irq) ++{ ++ move_irq(irq); ++ if ((irq_desc[irq].status & (IRQ_PENDING | IRQ_DISABLED)) ++ == (IRQ_PENDING | IRQ_DISABLED)) ++ mask_IO_APIC_irq(irq); ++ ack_APIC_irq(); ++} ++ ++/* ++ * Level triggered interrupts can just be masked, ++ * and shutting down and starting up the interrupt ++ * is the same as enabling and disabling them -- except ++ * with a startup need to return a "was pending" value. ++ * ++ * Level triggered interrupts are special because we ++ * do not touch any IO-APIC register while handling ++ * them. We ack the APIC in the end-IRQ handler, not ++ * in the start-IRQ-handler. Protection against reentrance ++ * from the same interrupt is still provided, both by the ++ * generic IRQ layer and by the fact that an unacked local ++ * APIC does not accept IRQs. ++ */ ++static unsigned int startup_level_ioapic_irq (unsigned int irq) ++{ ++ unmask_IO_APIC_irq(irq); ++ ++ return 0; /* don't check for pending */ ++} ++ ++static void end_level_ioapic_irq (unsigned int irq) ++{ ++ unsigned long v; ++ int i; ++ ++ move_irq(irq); ++/* ++ * It appears there is an erratum which affects at least version 0x11 ++ * of I/O APIC (that's the 82093AA and cores integrated into various ++ * chipsets). Under certain conditions a level-triggered interrupt is ++ * erroneously delivered as edge-triggered one but the respective IRR ++ * bit gets set nevertheless. As a result the I/O unit expects an EOI ++ * message but it will never arrive and further interrupts are blocked ++ * from the source. The exact reason is so far unknown, but the ++ * phenomenon was observed when two consecutive interrupt requests ++ * from a given source get delivered to the same CPU and the source is ++ * temporarily disabled in between. ++ * ++ * A workaround is to simulate an EOI message manually. We achieve it ++ * by setting the trigger mode to edge and then to level when the edge ++ * trigger mode gets detected in the TMR of a local APIC for a ++ * level-triggered interrupt. We mask the source for the time of the ++ * operation to prevent an edge-triggered interrupt escaping meanwhile. ++ * The idea is from Manfred Spraul. --macro ++ */ ++ i = IO_APIC_VECTOR(irq); ++ ++ v = apic_read(APIC_TMR + ((i & ~0x1f) >> 1)); ++ ++ ack_APIC_irq(); ++ ++ if (!(v & (1 << (i & 0x1f)))) { ++ atomic_inc(&irq_mis_count); ++ spin_lock(&ioapic_lock); ++ __mask_and_edge_IO_APIC_irq(irq); ++ __unmask_and_level_IO_APIC_irq(irq); ++ spin_unlock(&ioapic_lock); ++ } ++} ++ ++#ifdef CONFIG_PCI_MSI ++static unsigned int startup_edge_ioapic_vector(unsigned int vector) ++{ ++ int irq = vector_to_irq(vector); ++ ++ return startup_edge_ioapic_irq(irq); ++} ++ ++static void ack_edge_ioapic_vector(unsigned int vector) ++{ ++ int irq = vector_to_irq(vector); ++ ++ move_native_irq(vector); ++ ack_edge_ioapic_irq(irq); ++} ++ ++static unsigned int startup_level_ioapic_vector (unsigned int vector) ++{ ++ int irq = vector_to_irq(vector); ++ ++ return startup_level_ioapic_irq (irq); ++} ++ ++static void end_level_ioapic_vector (unsigned int vector) ++{ ++ int irq = vector_to_irq(vector); ++ ++ move_native_irq(vector); ++ end_level_ioapic_irq(irq); ++} ++ ++static void mask_IO_APIC_vector (unsigned int vector) ++{ ++ int irq = vector_to_irq(vector); ++ ++ mask_IO_APIC_irq(irq); ++} ++ ++static void unmask_IO_APIC_vector (unsigned int vector) ++{ ++ int irq = vector_to_irq(vector); ++ ++ unmask_IO_APIC_irq(irq); ++} ++ ++#ifdef CONFIG_SMP ++static void set_ioapic_affinity_vector (unsigned int vector, ++ cpumask_t cpu_mask) ++{ ++ int irq = vector_to_irq(vector); ++ ++ set_native_irq_info(vector, cpu_mask); ++ set_ioapic_affinity_irq(irq, cpu_mask); ++} ++#endif ++#endif ++ ++static int ioapic_retrigger(unsigned int irq) ++{ ++ send_IPI_self(IO_APIC_VECTOR(irq)); ++ ++ return 1; ++} ++ ++/* ++ * Level and edge triggered IO-APIC interrupts need different handling, ++ * so we use two separate IRQ descriptors. Edge triggered IRQs can be ++ * handled with the level-triggered descriptor, but that one has slightly ++ * more overhead. Level-triggered interrupts cannot be handled with the ++ * edge-triggered handler, without risking IRQ storms and other ugly ++ * races. ++ */ ++static struct hw_interrupt_type ioapic_edge_type __read_mostly = { ++ .typename = "IO-APIC-edge", ++ .startup = startup_edge_ioapic, ++ .shutdown = shutdown_edge_ioapic, ++ .enable = enable_edge_ioapic, ++ .disable = disable_edge_ioapic, ++ .ack = ack_edge_ioapic, ++ .end = end_edge_ioapic, ++#ifdef CONFIG_SMP ++ .set_affinity = set_ioapic_affinity, ++#endif ++ .retrigger = ioapic_retrigger, ++}; ++ ++static struct hw_interrupt_type ioapic_level_type __read_mostly = { ++ .typename = "IO-APIC-level", ++ .startup = startup_level_ioapic, ++ .shutdown = shutdown_level_ioapic, ++ .enable = enable_level_ioapic, ++ .disable = disable_level_ioapic, ++ .ack = mask_and_ack_level_ioapic, ++ .end = end_level_ioapic, ++#ifdef CONFIG_SMP ++ .set_affinity = set_ioapic_affinity, ++#endif ++ .retrigger = ioapic_retrigger, ++}; ++#endif /* !CONFIG_XEN */ ++ ++static inline void init_IO_APIC_traps(void) ++{ ++ int irq; ++ ++ /* ++ * NOTE! The local APIC isn't very good at handling ++ * multiple interrupts at the same interrupt level. ++ * As the interrupt level is determined by taking the ++ * vector number and shifting that right by 4, we ++ * want to spread these out a bit so that they don't ++ * all fall in the same interrupt level. ++ * ++ * Also, we've got to be careful not to trash gate ++ * 0x80, because int 0x80 is hm, kind of importantish. ;) ++ */ ++ for (irq = 0; irq < NR_IRQS ; irq++) { ++ int tmp = irq; ++ if (use_pci_vector()) { ++ if (!platform_legacy_irq(tmp)) ++ if ((tmp = vector_to_irq(tmp)) == -1) ++ continue; ++ } ++ if (IO_APIC_IRQ(tmp) && !IO_APIC_VECTOR(tmp)) { ++ /* ++ * Hmm.. We don't have an entry for this, ++ * so default to an old-fashioned 8259 ++ * interrupt if we can.. ++ */ ++ if (irq < 16) ++ make_8259A_irq(irq); ++#ifndef CONFIG_XEN ++ else ++ /* Strange. Oh, well.. */ ++ irq_desc[irq].chip = &no_irq_type; ++#endif ++ } ++ } ++} ++ ++#ifndef CONFIG_XEN ++static void enable_lapic_irq (unsigned int irq) ++{ ++ unsigned long v; ++ ++ v = apic_read(APIC_LVT0); ++ apic_write_around(APIC_LVT0, v & ~APIC_LVT_MASKED); ++} ++ ++static void disable_lapic_irq (unsigned int irq) ++{ ++ unsigned long v; ++ ++ v = apic_read(APIC_LVT0); ++ apic_write_around(APIC_LVT0, v | APIC_LVT_MASKED); ++} ++ ++static void ack_lapic_irq (unsigned int irq) ++{ ++ ack_APIC_irq(); ++} ++ ++static void end_lapic_irq (unsigned int i) { /* nothing */ } ++ ++static struct hw_interrupt_type lapic_irq_type __read_mostly = { ++ .typename = "local-APIC-edge", ++ .startup = NULL, /* startup_irq() not used for IRQ0 */ ++ .shutdown = NULL, /* shutdown_irq() not used for IRQ0 */ ++ .enable = enable_lapic_irq, ++ .disable = disable_lapic_irq, ++ .ack = ack_lapic_irq, ++ .end = end_lapic_irq ++}; ++ ++static void setup_nmi (void) ++{ ++ /* ++ * Dirty trick to enable the NMI watchdog ... ++ * We put the 8259A master into AEOI mode and ++ * unmask on all local APICs LVT0 as NMI. ++ * ++ * The idea to use the 8259A in AEOI mode ('8259A Virtual Wire') ++ * is from Maciej W. Rozycki - so we do not have to EOI from ++ * the NMI handler or the timer interrupt. ++ */ ++ apic_printk(APIC_VERBOSE, KERN_INFO "activating NMI Watchdog ..."); ++ ++ on_each_cpu(enable_NMI_through_LVT0, NULL, 1, 1); ++ ++ apic_printk(APIC_VERBOSE, " done.\n"); ++} ++ ++/* ++ * This looks a bit hackish but it's about the only one way of sending ++ * a few INTA cycles to 8259As and any associated glue logic. ICR does ++ * not support the ExtINT mode, unfortunately. We need to send these ++ * cycles as some i82489DX-based boards have glue logic that keeps the ++ * 8259A interrupt line asserted until INTA. --macro ++ */ ++static inline void unlock_ExtINT_logic(void) ++{ ++ int apic, pin, i; ++ struct IO_APIC_route_entry entry0, entry1; ++ unsigned char save_control, save_freq_select; ++ unsigned long flags; ++ ++ pin = find_isa_irq_pin(8, mp_INT); ++ apic = find_isa_irq_apic(8, mp_INT); ++ if (pin == -1) ++ return; ++ ++ spin_lock_irqsave(&ioapic_lock, flags); ++ *(((int *)&entry0) + 1) = io_apic_read(apic, 0x11 + 2 * pin); ++ *(((int *)&entry0) + 0) = io_apic_read(apic, 0x10 + 2 * pin); ++ spin_unlock_irqrestore(&ioapic_lock, flags); ++ clear_IO_APIC_pin(apic, pin); ++ ++ memset(&entry1, 0, sizeof(entry1)); ++ ++ entry1.dest_mode = 0; /* physical delivery */ ++ entry1.mask = 0; /* unmask IRQ now */ ++ entry1.dest.physical.physical_dest = hard_smp_processor_id(); ++ entry1.delivery_mode = dest_ExtINT; ++ entry1.polarity = entry0.polarity; ++ entry1.trigger = 0; ++ entry1.vector = 0; ++ ++ spin_lock_irqsave(&ioapic_lock, flags); ++ io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry1) + 1)); ++ io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry1) + 0)); ++ spin_unlock_irqrestore(&ioapic_lock, flags); ++ ++ save_control = CMOS_READ(RTC_CONTROL); ++ save_freq_select = CMOS_READ(RTC_FREQ_SELECT); ++ CMOS_WRITE((save_freq_select & ~RTC_RATE_SELECT) | 0x6, ++ RTC_FREQ_SELECT); ++ CMOS_WRITE(save_control | RTC_PIE, RTC_CONTROL); ++ ++ i = 100; ++ while (i-- > 0) { ++ mdelay(10); ++ if ((CMOS_READ(RTC_INTR_FLAGS) & RTC_PF) == RTC_PF) ++ i -= 10; ++ } ++ ++ CMOS_WRITE(save_control, RTC_CONTROL); ++ CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); ++ clear_IO_APIC_pin(apic, pin); ++ ++ spin_lock_irqsave(&ioapic_lock, flags); ++ io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry0) + 1)); ++ io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry0) + 0)); ++ spin_unlock_irqrestore(&ioapic_lock, flags); ++} ++ ++int timer_uses_ioapic_pin_0; ++ ++/* ++ * This code may look a bit paranoid, but it's supposed to cooperate with ++ * a wide range of boards and BIOS bugs. Fortunately only the timer IRQ ++ * is so screwy. Thanks to Brian Perkins for testing/hacking this beast ++ * fanatically on his truly buggy board. ++ */ ++static inline void check_timer(void) ++{ ++ int apic1, pin1, apic2, pin2; ++ int vector; ++ ++ /* ++ * get/set the timer IRQ vector: ++ */ ++ disable_8259A_irq(0); ++ vector = assign_irq_vector(0); ++ set_intr_gate(vector, interrupt[0]); ++ ++ /* ++ * Subtle, code in do_timer_interrupt() expects an AEOI ++ * mode for the 8259A whenever interrupts are routed ++ * through I/O APICs. Also IRQ0 has to be enabled in ++ * the 8259A which implies the virtual wire has to be ++ * disabled in the local APIC. ++ */ ++ apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT); ++ init_8259A(1); ++ timer_ack = 1; ++ if (timer_over_8254 > 0) ++ enable_8259A_irq(0); ++ ++ pin1 = find_isa_irq_pin(0, mp_INT); ++ apic1 = find_isa_irq_apic(0, mp_INT); ++ pin2 = ioapic_i8259.pin; ++ apic2 = ioapic_i8259.apic; ++ ++ if (pin1 == 0) ++ timer_uses_ioapic_pin_0 = 1; ++ ++ printk(KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n", ++ vector, apic1, pin1, apic2, pin2); ++ ++ if (pin1 != -1) { ++ /* ++ * Ok, does IRQ0 through the IOAPIC work? ++ */ ++ unmask_IO_APIC_irq(0); ++ if (timer_irq_works()) { ++ if (nmi_watchdog == NMI_IO_APIC) { ++ disable_8259A_irq(0); ++ setup_nmi(); ++ enable_8259A_irq(0); ++ } ++ if (disable_timer_pin_1 > 0) ++ clear_IO_APIC_pin(0, pin1); ++ return; ++ } ++ clear_IO_APIC_pin(apic1, pin1); ++ printk(KERN_ERR "..MP-BIOS bug: 8254 timer not connected to " ++ "IO-APIC\n"); ++ } ++ ++ printk(KERN_INFO "...trying to set up timer (IRQ0) through the 8259A ... "); ++ if (pin2 != -1) { ++ printk("\n..... (found pin %d) ...", pin2); ++ /* ++ * legacy devices should be connected to IO APIC #0 ++ */ ++ setup_ExtINT_IRQ0_pin(apic2, pin2, vector); ++ if (timer_irq_works()) { ++ printk("works.\n"); ++ if (pin1 != -1) ++ replace_pin_at_irq(0, apic1, pin1, apic2, pin2); ++ else ++ add_pin_to_irq(0, apic2, pin2); ++ if (nmi_watchdog == NMI_IO_APIC) { ++ setup_nmi(); ++ } ++ return; ++ } ++ /* ++ * Cleanup, just in case ... ++ */ ++ clear_IO_APIC_pin(apic2, pin2); ++ } ++ printk(" failed.\n"); ++ ++ if (nmi_watchdog == NMI_IO_APIC) { ++ printk(KERN_WARNING "timer doesn't work through the IO-APIC - disabling NMI Watchdog!\n"); ++ nmi_watchdog = 0; ++ } ++ ++ printk(KERN_INFO "...trying to set up timer as Virtual Wire IRQ..."); ++ ++ disable_8259A_irq(0); ++ irq_desc[0].chip = &lapic_irq_type; ++ apic_write_around(APIC_LVT0, APIC_DM_FIXED | vector); /* Fixed mode */ ++ enable_8259A_irq(0); ++ ++ if (timer_irq_works()) { ++ printk(" works.\n"); ++ return; ++ } ++ apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | vector); ++ printk(" failed.\n"); ++ ++ printk(KERN_INFO "...trying to set up timer as ExtINT IRQ..."); ++ ++ timer_ack = 0; ++ init_8259A(0); ++ make_8259A_irq(0); ++ apic_write_around(APIC_LVT0, APIC_DM_EXTINT); ++ ++ unlock_ExtINT_logic(); ++ ++ if (timer_irq_works()) { ++ printk(" works.\n"); ++ return; ++ } ++ printk(" failed :(.\n"); ++ panic("IO-APIC + timer doesn't work! Boot with apic=debug and send a " ++ "report. Then try booting with the 'noapic' option"); ++} ++#else ++int timer_uses_ioapic_pin_0 = 0; ++#define check_timer() ((void)0) ++#endif ++ ++/* ++ * ++ * IRQ's that are handled by the PIC in the MPS IOAPIC case. ++ * - IRQ2 is the cascade IRQ, and cannot be a io-apic IRQ. ++ * Linux doesn't really care, as it's not actually used ++ * for any interrupt handling anyway. ++ */ ++#define PIC_IRQS (1 << PIC_CASCADE_IR) ++ ++void __init setup_IO_APIC(void) ++{ ++ enable_IO_APIC(); ++ ++ if (acpi_ioapic) ++ io_apic_irqs = ~0; /* all IRQs go through IOAPIC */ ++ else ++ io_apic_irqs = ~PIC_IRQS; ++ ++ printk("ENABLING IO-APIC IRQs\n"); ++ ++ /* ++ * Set up IO-APIC IRQ routing. ++ */ ++ if (!acpi_ioapic) ++ setup_ioapic_ids_from_mpc(); ++#ifndef CONFIG_XEN ++ sync_Arb_IDs(); ++#endif ++ setup_IO_APIC_irqs(); ++ init_IO_APIC_traps(); ++ check_timer(); ++ if (!acpi_ioapic) ++ print_IO_APIC(); ++} ++ ++static int __init setup_disable_8254_timer(char *s) ++{ ++ timer_over_8254 = -1; ++ return 1; ++} ++static int __init setup_enable_8254_timer(char *s) ++{ ++ timer_over_8254 = 2; ++ return 1; ++} ++ ++__setup("disable_8254_timer", setup_disable_8254_timer); ++__setup("enable_8254_timer", setup_enable_8254_timer); ++ ++/* ++ * Called after all the initialization is done. If we didnt find any ++ * APIC bugs then we can allow the modify fast path ++ */ ++ ++static int __init io_apic_bug_finalize(void) ++{ ++ if(sis_apic_bug == -1) ++ sis_apic_bug = 0; ++ if (is_initial_xendomain()) { ++ struct xen_platform_op op = { .cmd = XENPF_platform_quirk }; ++ op.u.platform_quirk.quirk_id = sis_apic_bug ? ++ QUIRK_IOAPIC_BAD_REGSEL : QUIRK_IOAPIC_GOOD_REGSEL; ++ VOID(HYPERVISOR_platform_op(&op)); ++ } ++ return 0; ++} ++ ++late_initcall(io_apic_bug_finalize); ++ ++#ifndef CONFIG_XEN ++ ++struct sysfs_ioapic_data { ++ struct sys_device dev; ++ struct IO_APIC_route_entry entry[0]; ++}; ++static struct sysfs_ioapic_data * mp_ioapic_data[MAX_IO_APICS]; ++ ++static int ioapic_suspend(struct sys_device *dev, pm_message_t state) ++{ ++ struct IO_APIC_route_entry *entry; ++ struct sysfs_ioapic_data *data; ++ unsigned long flags; ++ int i; ++ ++ data = container_of(dev, struct sysfs_ioapic_data, dev); ++ entry = data->entry; ++ spin_lock_irqsave(&ioapic_lock, flags); ++ for (i = 0; i < nr_ioapic_registers[dev->id]; i ++, entry ++ ) { ++ *(((int *)entry) + 1) = io_apic_read(dev->id, 0x11 + 2 * i); ++ *(((int *)entry) + 0) = io_apic_read(dev->id, 0x10 + 2 * i); ++ } ++ spin_unlock_irqrestore(&ioapic_lock, flags); ++ ++ return 0; ++} ++ ++static int ioapic_resume(struct sys_device *dev) ++{ ++ struct IO_APIC_route_entry *entry; ++ struct sysfs_ioapic_data *data; ++ unsigned long flags; ++ union IO_APIC_reg_00 reg_00; ++ int i; ++ ++ data = container_of(dev, struct sysfs_ioapic_data, dev); ++ entry = data->entry; ++ ++ spin_lock_irqsave(&ioapic_lock, flags); ++ reg_00.raw = io_apic_read(dev->id, 0); ++ if (reg_00.bits.ID != mp_ioapics[dev->id].mpc_apicid) { ++ reg_00.bits.ID = mp_ioapics[dev->id].mpc_apicid; ++ io_apic_write(dev->id, 0, reg_00.raw); ++ } ++ for (i = 0; i < nr_ioapic_registers[dev->id]; i ++, entry ++ ) { ++ io_apic_write(dev->id, 0x11+2*i, *(((int *)entry)+1)); ++ io_apic_write(dev->id, 0x10+2*i, *(((int *)entry)+0)); ++ } ++ spin_unlock_irqrestore(&ioapic_lock, flags); ++ ++ return 0; ++} ++ ++static struct sysdev_class ioapic_sysdev_class = { ++ set_kset_name("ioapic"), ++ .suspend = ioapic_suspend, ++ .resume = ioapic_resume, ++}; ++ ++static int __init ioapic_init_sysfs(void) ++{ ++ struct sys_device * dev; ++ int i, size, error = 0; ++ ++ error = sysdev_class_register(&ioapic_sysdev_class); ++ if (error) ++ return error; ++ ++ for (i = 0; i < nr_ioapics; i++ ) { ++ size = sizeof(struct sys_device) + nr_ioapic_registers[i] ++ * sizeof(struct IO_APIC_route_entry); ++ mp_ioapic_data[i] = kmalloc(size, GFP_KERNEL); ++ if (!mp_ioapic_data[i]) { ++ printk(KERN_ERR "Can't suspend/resume IOAPIC %d\n", i); ++ continue; ++ } ++ memset(mp_ioapic_data[i], 0, size); ++ dev = &mp_ioapic_data[i]->dev; ++ dev->id = i; ++ dev->cls = &ioapic_sysdev_class; ++ error = sysdev_register(dev); ++ if (error) { ++ kfree(mp_ioapic_data[i]); ++ mp_ioapic_data[i] = NULL; ++ printk(KERN_ERR "Can't suspend/resume IOAPIC %d\n", i); ++ continue; ++ } ++ } ++ ++ return 0; ++} ++ ++device_initcall(ioapic_init_sysfs); ++ ++#endif /* CONFIG_XEN */ ++ ++/* -------------------------------------------------------------------------- ++ ACPI-based IOAPIC Configuration ++ -------------------------------------------------------------------------- */ ++ ++#ifdef CONFIG_ACPI ++ ++int __init io_apic_get_unique_id (int ioapic, int apic_id) ++{ ++#ifndef CONFIG_XEN ++ union IO_APIC_reg_00 reg_00; ++ static physid_mask_t apic_id_map = PHYSID_MASK_NONE; ++ physid_mask_t tmp; ++ unsigned long flags; ++ int i = 0; ++ ++ /* ++ * The P4 platform supports up to 256 APIC IDs on two separate APIC ++ * buses (one for LAPICs, one for IOAPICs), where predecessors only ++ * supports up to 16 on one shared APIC bus. ++ * ++ * TBD: Expand LAPIC/IOAPIC support on P4-class systems to take full ++ * advantage of new APIC bus architecture. ++ */ ++ ++ if (physids_empty(apic_id_map)) ++ apic_id_map = ioapic_phys_id_map(phys_cpu_present_map); ++ ++ spin_lock_irqsave(&ioapic_lock, flags); ++ reg_00.raw = io_apic_read(ioapic, 0); ++ spin_unlock_irqrestore(&ioapic_lock, flags); ++ ++ if (apic_id >= get_physical_broadcast()) { ++ printk(KERN_WARNING "IOAPIC[%d]: Invalid apic_id %d, trying " ++ "%d\n", ioapic, apic_id, reg_00.bits.ID); ++ apic_id = reg_00.bits.ID; ++ } ++ ++ /* ++ * Every APIC in a system must have a unique ID or we get lots of nice ++ * 'stuck on smp_invalidate_needed IPI wait' messages. ++ */ ++ if (check_apicid_used(apic_id_map, apic_id)) { ++ ++ for (i = 0; i < get_physical_broadcast(); i++) { ++ if (!check_apicid_used(apic_id_map, i)) ++ break; ++ } ++ ++ if (i == get_physical_broadcast()) ++ panic("Max apic_id exceeded!\n"); ++ ++ printk(KERN_WARNING "IOAPIC[%d]: apic_id %d already used, " ++ "trying %d\n", ioapic, apic_id, i); ++ ++ apic_id = i; ++ } ++ ++ tmp = apicid_to_cpu_present(apic_id); ++ physids_or(apic_id_map, apic_id_map, tmp); ++ ++ if (reg_00.bits.ID != apic_id) { ++ reg_00.bits.ID = apic_id; ++ ++ spin_lock_irqsave(&ioapic_lock, flags); ++ io_apic_write(ioapic, 0, reg_00.raw); ++ reg_00.raw = io_apic_read(ioapic, 0); ++ spin_unlock_irqrestore(&ioapic_lock, flags); ++ ++ /* Sanity check */ ++ if (reg_00.bits.ID != apic_id) { ++ printk("IOAPIC[%d]: Unable to change apic_id!\n", ioapic); ++ return -1; ++ } ++ } ++ ++ apic_printk(APIC_VERBOSE, KERN_INFO ++ "IOAPIC[%d]: Assigned apic_id %d\n", ioapic, apic_id); ++#endif /* !CONFIG_XEN */ ++ ++ return apic_id; ++} ++ ++ ++int __init io_apic_get_version (int ioapic) ++{ ++ union IO_APIC_reg_01 reg_01; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&ioapic_lock, flags); ++ reg_01.raw = io_apic_read(ioapic, 1); ++ spin_unlock_irqrestore(&ioapic_lock, flags); ++ ++ return reg_01.bits.version; ++} ++ ++ ++int __init io_apic_get_redir_entries (int ioapic) ++{ ++ union IO_APIC_reg_01 reg_01; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&ioapic_lock, flags); ++ reg_01.raw = io_apic_read(ioapic, 1); ++ spin_unlock_irqrestore(&ioapic_lock, flags); ++ ++ return reg_01.bits.entries; ++} ++ ++ ++int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int active_high_low) ++{ ++ struct IO_APIC_route_entry entry; ++ unsigned long flags; ++ ++ if (!IO_APIC_IRQ(irq)) { ++ printk(KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n", ++ ioapic); ++ return -EINVAL; ++ } ++ ++ /* ++ * Generate a PCI IRQ routing entry and program the IOAPIC accordingly. ++ * Note that we mask (disable) IRQs now -- these get enabled when the ++ * corresponding device driver registers for this IRQ. ++ */ ++ ++ memset(&entry,0,sizeof(entry)); ++ ++ entry.delivery_mode = INT_DELIVERY_MODE; ++ entry.dest_mode = INT_DEST_MODE; ++ entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS); ++ entry.trigger = edge_level; ++ entry.polarity = active_high_low; ++ entry.mask = 1; ++ ++ /* ++ * IRQs < 16 are already in the irq_2_pin[] map ++ */ ++ if (irq >= 16) ++ add_pin_to_irq(irq, ioapic, pin); ++ ++ entry.vector = assign_irq_vector(irq); ++ ++ apic_printk(APIC_DEBUG, KERN_DEBUG "IOAPIC[%d]: Set PCI routing entry " ++ "(%d-%d -> 0x%x -> IRQ %d Mode:%i Active:%i)\n", ioapic, ++ mp_ioapics[ioapic].mpc_apicid, pin, entry.vector, irq, ++ edge_level, active_high_low); ++ ++ ioapic_register_intr(irq, entry.vector, edge_level); ++ ++ if (!ioapic && (irq < 16)) ++ disable_8259A_irq(irq); ++ ++ spin_lock_irqsave(&ioapic_lock, flags); ++ io_apic_write(ioapic, 0x11+2*pin, *(((int *)&entry)+1)); ++ io_apic_write(ioapic, 0x10+2*pin, *(((int *)&entry)+0)); ++ set_native_irq_info(use_pci_vector() ? entry.vector : irq, TARGET_CPUS); ++ spin_unlock_irqrestore(&ioapic_lock, flags); ++ ++ return 0; ++} ++ ++#endif /* CONFIG_ACPI */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/arch/x86/kernel/ioport_32-xen.c 2008-01-28 12:24:19.000000000 +0100 +@@ -0,0 +1,123 @@ ++/* ++ * linux/arch/i386/kernel/ioport.c ++ * ++ * This contains the io-permission bitmap code - written by obz, with changes ++ * by Linus. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* Set EXTENT bits starting at BASE in BITMAP to value TURN_ON. */ ++static void set_bitmap(unsigned long *bitmap, unsigned int base, unsigned int extent, int new_value) ++{ ++ unsigned long mask; ++ unsigned long *bitmap_base = bitmap + (base / BITS_PER_LONG); ++ unsigned int low_index = base & (BITS_PER_LONG-1); ++ int length = low_index + extent; ++ ++ if (low_index != 0) { ++ mask = (~0UL << low_index); ++ if (length < BITS_PER_LONG) ++ mask &= ~(~0UL << length); ++ if (new_value) ++ *bitmap_base++ |= mask; ++ else ++ *bitmap_base++ &= ~mask; ++ length -= BITS_PER_LONG; ++ } ++ ++ mask = (new_value ? ~0UL : 0UL); ++ while (length >= BITS_PER_LONG) { ++ *bitmap_base++ = mask; ++ length -= BITS_PER_LONG; ++ } ++ ++ if (length > 0) { ++ mask = ~(~0UL << length); ++ if (new_value) ++ *bitmap_base++ |= mask; ++ else ++ *bitmap_base++ &= ~mask; ++ } ++} ++ ++ ++/* ++ * this changes the io permissions bitmap in the current task. ++ */ ++asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on) ++{ ++ struct thread_struct * t = ¤t->thread; ++ unsigned long *bitmap; ++ struct physdev_set_iobitmap set_iobitmap; ++ ++ if ((from + num <= from) || (from + num > IO_BITMAP_BITS)) ++ return -EINVAL; ++ if (turn_on && !capable(CAP_SYS_RAWIO)) ++ return -EPERM; ++ ++ /* ++ * If it's the first ioperm() call in this thread's lifetime, set the ++ * IO bitmap up. ioperm() is much less timing critical than clone(), ++ * this is why we delay this operation until now: ++ */ ++ if (!t->io_bitmap_ptr) { ++ bitmap = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL); ++ if (!bitmap) ++ return -ENOMEM; ++ ++ memset(bitmap, 0xff, IO_BITMAP_BYTES); ++ t->io_bitmap_ptr = bitmap; ++ set_thread_flag(TIF_IO_BITMAP); ++ ++ set_xen_guest_handle(set_iobitmap.bitmap, (char *)bitmap); ++ set_iobitmap.nr_ports = IO_BITMAP_BITS; ++ WARN_ON(HYPERVISOR_physdev_op(PHYSDEVOP_set_iobitmap, ++ &set_iobitmap)); ++ } ++ ++ set_bitmap(t->io_bitmap_ptr, from, num, !turn_on); ++ ++ return 0; ++} ++ ++/* ++ * sys_iopl has to be used when you want to access the IO ports ++ * beyond the 0x3ff range: to get the full 65536 ports bitmapped ++ * you'd need 8kB of bitmaps/process, which is a bit excessive. ++ * ++ * Here we just change the eflags value on the stack: we allow ++ * only the super-user to do it. This depends on the stack-layout ++ * on system-call entry - see also fork() and the signal handling ++ * code. ++ */ ++ ++asmlinkage long sys_iopl(unsigned long unused) ++{ ++ volatile struct pt_regs * regs = (struct pt_regs *) &unused; ++ unsigned int level = regs->ebx; ++ struct thread_struct *t = ¤t->thread; ++ unsigned int old = (t->iopl >> 12) & 3; ++ ++ if (level > 3) ++ return -EINVAL; ++ /* Trying to gain more privileges? */ ++ if (level > old) { ++ if (!capable(CAP_SYS_RAWIO)) ++ return -EPERM; ++ } ++ t->iopl = level << 12; ++ set_iopl_mask(t->iopl); ++ return 0; ++} +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/arch/x86/kernel/irq_32-xen.c 2008-10-29 09:55:56.000000000 +0100 +@@ -0,0 +1,324 @@ ++/* ++ * linux/arch/i386/kernel/irq.c ++ * ++ * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar ++ * ++ * This file contains the lowest level x86-specific interrupt ++ * entry, irq-stacks and irq statistics code. All the remaining ++ * irq logic is done by the generic kernel/irq/ code and ++ * by the x86-specific irq controller code. (e.g. i8259.c and ++ * io_apic.c.) ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++DEFINE_PER_CPU(irq_cpustat_t, irq_stat) ____cacheline_internodealigned_in_smp; ++EXPORT_PER_CPU_SYMBOL(irq_stat); ++ ++#ifndef CONFIG_X86_LOCAL_APIC ++/* ++ * 'what should we do if we get a hw irq event on an illegal vector'. ++ * each architecture has to answer this themselves. ++ */ ++void ack_bad_irq(unsigned int irq) ++{ ++ printk("unexpected IRQ trap at vector %02x\n", irq); ++} ++#endif ++ ++#ifdef CONFIG_4KSTACKS ++/* ++ * per-CPU IRQ handling contexts (thread information and stack) ++ */ ++union irq_ctx { ++ struct thread_info tinfo; ++ u32 stack[THREAD_SIZE/sizeof(u32)]; ++}; ++ ++static union irq_ctx *hardirq_ctx[NR_CPUS] __read_mostly; ++static union irq_ctx *softirq_ctx[NR_CPUS] __read_mostly; ++#endif ++ ++/* ++ * do_IRQ handles all normal device IRQ's (the special ++ * SMP cross-CPU interrupts have their own specific ++ * handlers). ++ */ ++fastcall unsigned int do_IRQ(struct pt_regs *regs) ++{ ++ /* high bit used in ret_from_ code */ ++ int irq = ~regs->orig_eax; ++#ifdef CONFIG_4KSTACKS ++ union irq_ctx *curctx, *irqctx; ++ u32 *isp; ++#endif ++ ++ if (unlikely((unsigned)irq >= NR_IRQS)) { ++ printk(KERN_EMERG "%s: cannot handle IRQ %d\n", ++ __FUNCTION__, irq); ++ BUG(); ++ } ++ ++ /*irq_enter();*/ ++#ifdef CONFIG_DEBUG_STACKOVERFLOW ++ /* Debugging check for stack overflow: is there less than 1KB free? */ ++ { ++ long esp; ++ ++ __asm__ __volatile__("andl %%esp,%0" : ++ "=r" (esp) : "0" (THREAD_SIZE - 1)); ++ if (unlikely(esp < (sizeof(struct thread_info) + STACK_WARN))) { ++ printk("do_IRQ: stack overflow: %ld\n", ++ esp - sizeof(struct thread_info)); ++ dump_stack(); ++ } ++ } ++#endif ++ ++#ifdef CONFIG_4KSTACKS ++ ++ curctx = (union irq_ctx *) current_thread_info(); ++ irqctx = hardirq_ctx[smp_processor_id()]; ++ ++ /* ++ * this is where we switch to the IRQ stack. However, if we are ++ * already using the IRQ stack (because we interrupted a hardirq ++ * handler) we can't do that and just have to keep using the ++ * current stack (which is the irq stack already after all) ++ */ ++ if (curctx != irqctx) { ++ int arg1, arg2, ebx; ++ ++ /* build the stack frame on the IRQ stack */ ++ isp = (u32*) ((char*)irqctx + sizeof(*irqctx)); ++ irqctx->tinfo.task = curctx->tinfo.task; ++ irqctx->tinfo.previous_esp = current_stack_pointer; ++ ++ /* ++ * Copy the softirq bits in preempt_count so that the ++ * softirq checks work in the hardirq context. ++ */ ++ irqctx->tinfo.preempt_count = ++ (irqctx->tinfo.preempt_count & ~SOFTIRQ_MASK) | ++ (curctx->tinfo.preempt_count & SOFTIRQ_MASK); ++ ++ asm volatile( ++ " xchgl %%ebx,%%esp \n" ++ " call __do_IRQ \n" ++ " movl %%ebx,%%esp \n" ++ : "=a" (arg1), "=d" (arg2), "=b" (ebx) ++ : "0" (irq), "1" (regs), "2" (isp) ++ : "memory", "cc", "ecx" ++ ); ++ } else ++#endif ++ __do_IRQ(irq, regs); ++ ++ /*irq_exit();*/ ++ ++ return 1; ++} ++ ++#ifdef CONFIG_4KSTACKS ++ ++/* ++ * These should really be __section__(".bss.page_aligned") as well, but ++ * gcc's 3.0 and earlier don't handle that correctly. ++ */ ++static char softirq_stack[NR_CPUS * THREAD_SIZE] ++ __attribute__((__aligned__(THREAD_SIZE))); ++ ++static char hardirq_stack[NR_CPUS * THREAD_SIZE] ++ __attribute__((__aligned__(THREAD_SIZE))); ++ ++/* ++ * allocate per-cpu stacks for hardirq and for softirq processing ++ */ ++void irq_ctx_init(int cpu) ++{ ++ union irq_ctx *irqctx; ++ ++ if (hardirq_ctx[cpu]) ++ return; ++ ++ irqctx = (union irq_ctx*) &hardirq_stack[cpu*THREAD_SIZE]; ++ irqctx->tinfo.task = NULL; ++ irqctx->tinfo.exec_domain = NULL; ++ irqctx->tinfo.cpu = cpu; ++ irqctx->tinfo.preempt_count = HARDIRQ_OFFSET; ++ irqctx->tinfo.addr_limit = MAKE_MM_SEG(0); ++ ++ hardirq_ctx[cpu] = irqctx; ++ ++ irqctx = (union irq_ctx*) &softirq_stack[cpu*THREAD_SIZE]; ++ irqctx->tinfo.task = NULL; ++ irqctx->tinfo.exec_domain = NULL; ++ irqctx->tinfo.cpu = cpu; ++ irqctx->tinfo.preempt_count = 0; ++ irqctx->tinfo.addr_limit = MAKE_MM_SEG(0); ++ ++ softirq_ctx[cpu] = irqctx; ++ ++ printk("CPU %u irqstacks, hard=%p soft=%p\n", ++ cpu,hardirq_ctx[cpu],softirq_ctx[cpu]); ++} ++ ++void irq_ctx_exit(int cpu) ++{ ++ hardirq_ctx[cpu] = NULL; ++} ++ ++extern asmlinkage void __do_softirq(void); ++ ++asmlinkage void do_softirq(void) ++{ ++ unsigned long flags; ++ struct thread_info *curctx; ++ union irq_ctx *irqctx; ++ u32 *isp; ++ ++ if (in_interrupt()) ++ return; ++ ++ local_irq_save(flags); ++ ++ if (local_softirq_pending()) { ++ curctx = current_thread_info(); ++ irqctx = softirq_ctx[smp_processor_id()]; ++ irqctx->tinfo.task = curctx->task; ++ irqctx->tinfo.previous_esp = current_stack_pointer; ++ ++ /* build the stack frame on the softirq stack */ ++ isp = (u32*) ((char*)irqctx + sizeof(*irqctx)); ++ ++ asm volatile( ++ " xchgl %%ebx,%%esp \n" ++ " call __do_softirq \n" ++ " movl %%ebx,%%esp \n" ++ : "=b"(isp) ++ : "0"(isp) ++ : "memory", "cc", "edx", "ecx", "eax" ++ ); ++ /* ++ * Shouldnt happen, we returned above if in_interrupt(): ++ */ ++ WARN_ON_ONCE(softirq_count()); ++ } ++ ++ local_irq_restore(flags); ++} ++ ++EXPORT_SYMBOL(do_softirq); ++#endif ++ ++/* ++ * Interrupt statistics: ++ */ ++ ++atomic_t irq_err_count; ++ ++/* ++ * /proc/interrupts printing: ++ */ ++ ++int show_interrupts(struct seq_file *p, void *v) ++{ ++ int i = *(loff_t *) v, j; ++ struct irqaction * action; ++ unsigned long flags; ++ ++ if (i == 0) { ++ seq_printf(p, " "); ++ for_each_online_cpu(j) ++ seq_printf(p, "CPU%-8d",j); ++ seq_putc(p, '\n'); ++ } ++ ++ if (i < NR_IRQS) { ++ spin_lock_irqsave(&irq_desc[i].lock, flags); ++ action = irq_desc[i].action; ++ if (!action) ++ goto skip; ++ seq_printf(p, "%3d: ",i); ++#ifndef CONFIG_SMP ++ seq_printf(p, "%10u ", kstat_irqs(i)); ++#else ++ for_each_online_cpu(j) ++ seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); ++#endif ++ seq_printf(p, " %14s", irq_desc[i].chip->typename); ++ seq_printf(p, " %s", action->name); ++ ++ for (action=action->next; action; action = action->next) ++ seq_printf(p, ", %s", action->name); ++ ++ seq_putc(p, '\n'); ++skip: ++ spin_unlock_irqrestore(&irq_desc[i].lock, flags); ++ } else if (i == NR_IRQS) { ++ seq_printf(p, "NMI: "); ++ for_each_online_cpu(j) ++ seq_printf(p, "%10u ", nmi_count(j)); ++ seq_putc(p, '\n'); ++#ifdef CONFIG_X86_LOCAL_APIC ++ seq_printf(p, "LOC: "); ++ for_each_online_cpu(j) ++ seq_printf(p, "%10u ", ++ per_cpu(irq_stat,j).apic_timer_irqs); ++ seq_putc(p, '\n'); ++#endif ++ seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count)); ++#if defined(CONFIG_X86_IO_APIC) ++ seq_printf(p, "MIS: %10u\n", atomic_read(&irq_mis_count)); ++#endif ++ } ++ return 0; ++} ++ ++#ifdef CONFIG_HOTPLUG_CPU ++ ++void fixup_irqs(cpumask_t map) ++{ ++ unsigned int irq; ++ static int warned; ++ ++ for (irq = 0; irq < NR_IRQS; irq++) { ++ cpumask_t mask; ++ if (irq == 2) ++ continue; ++ ++ cpus_and(mask, irq_desc[irq].affinity, map); ++ if (any_online_cpu(mask) == NR_CPUS) { ++ /*printk("Breaking affinity for irq %i\n", irq);*/ ++ mask = map; ++ } ++ if (irq_desc[irq].chip->set_affinity) ++ irq_desc[irq].chip->set_affinity(irq, mask); ++ else if (irq_desc[irq].action && !(warned++)) ++ printk("Cannot set affinity for irq %i\n", irq); ++ } ++ ++#if 0 ++ barrier(); ++ /* Ingo Molnar says: "after the IO-APIC masks have been redirected ++ [note the nop - the interrupt-enable boundary on x86 is two ++ instructions from sti] - to flush out pending hardirqs and ++ IPIs. After this point nothing is supposed to reach this CPU." */ ++ __asm__ __volatile__("sti; nop; cli"); ++ barrier(); ++#else ++ /* That doesn't seem sufficient. Give it 1ms. */ ++ local_irq_enable(); ++ mdelay(1); ++ local_irq_disable(); ++#endif ++} ++#endif ++ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/arch/x86/kernel/ldt_32-xen.c 2007-06-12 13:12:48.000000000 +0200 +@@ -0,0 +1,270 @@ ++/* ++ * linux/kernel/ldt.c ++ * ++ * Copyright (C) 1992 Krishna Balasubramanian and Linus Torvalds ++ * Copyright (C) 1999 Ingo Molnar ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef CONFIG_SMP /* avoids "defined but not used" warnig */ ++static void flush_ldt(void *null) ++{ ++ if (current->active_mm) ++ load_LDT(¤t->active_mm->context); ++} ++#endif ++ ++static int alloc_ldt(mm_context_t *pc, int mincount, int reload) ++{ ++ void *oldldt; ++ void *newldt; ++ int oldsize; ++ ++ if (mincount <= pc->size) ++ return 0; ++ oldsize = pc->size; ++ mincount = (mincount+511)&(~511); ++ if (mincount*LDT_ENTRY_SIZE > PAGE_SIZE) ++ newldt = vmalloc(mincount*LDT_ENTRY_SIZE); ++ else ++ newldt = kmalloc(mincount*LDT_ENTRY_SIZE, GFP_KERNEL); ++ ++ if (!newldt) ++ return -ENOMEM; ++ ++ if (oldsize) ++ memcpy(newldt, pc->ldt, oldsize*LDT_ENTRY_SIZE); ++ oldldt = pc->ldt; ++ memset(newldt+oldsize*LDT_ENTRY_SIZE, 0, (mincount-oldsize)*LDT_ENTRY_SIZE); ++ pc->ldt = newldt; ++ wmb(); ++ pc->size = mincount; ++ wmb(); ++ ++ if (reload) { ++#ifdef CONFIG_SMP ++ cpumask_t mask; ++ preempt_disable(); ++#endif ++ make_pages_readonly( ++ pc->ldt, ++ (pc->size * LDT_ENTRY_SIZE) / PAGE_SIZE, ++ XENFEAT_writable_descriptor_tables); ++ load_LDT(pc); ++#ifdef CONFIG_SMP ++ mask = cpumask_of_cpu(smp_processor_id()); ++ if (!cpus_equal(current->mm->cpu_vm_mask, mask)) ++ smp_call_function(flush_ldt, NULL, 1, 1); ++ preempt_enable(); ++#endif ++ } ++ if (oldsize) { ++ make_pages_writable( ++ oldldt, ++ (oldsize * LDT_ENTRY_SIZE) / PAGE_SIZE, ++ XENFEAT_writable_descriptor_tables); ++ if (oldsize*LDT_ENTRY_SIZE > PAGE_SIZE) ++ vfree(oldldt); ++ else ++ kfree(oldldt); ++ } ++ return 0; ++} ++ ++static inline int copy_ldt(mm_context_t *new, mm_context_t *old) ++{ ++ int err = alloc_ldt(new, old->size, 0); ++ if (err < 0) ++ return err; ++ memcpy(new->ldt, old->ldt, old->size*LDT_ENTRY_SIZE); ++ make_pages_readonly( ++ new->ldt, ++ (new->size * LDT_ENTRY_SIZE) / PAGE_SIZE, ++ XENFEAT_writable_descriptor_tables); ++ return 0; ++} ++ ++/* ++ * we do not have to muck with descriptors here, that is ++ * done in switch_mm() as needed. ++ */ ++int init_new_context(struct task_struct *tsk, struct mm_struct *mm) ++{ ++ struct mm_struct * old_mm; ++ int retval = 0; ++ ++ init_MUTEX(&mm->context.sem); ++ mm->context.size = 0; ++ mm->context.has_foreign_mappings = 0; ++ old_mm = current->mm; ++ if (old_mm && old_mm->context.size > 0) { ++ down(&old_mm->context.sem); ++ retval = copy_ldt(&mm->context, &old_mm->context); ++ up(&old_mm->context.sem); ++ } ++ return retval; ++} ++ ++/* ++ * No need to lock the MM as we are the last user ++ */ ++void destroy_context(struct mm_struct *mm) ++{ ++ if (mm->context.size) { ++ if (mm == current->active_mm) ++ clear_LDT(); ++ make_pages_writable( ++ mm->context.ldt, ++ (mm->context.size * LDT_ENTRY_SIZE) / PAGE_SIZE, ++ XENFEAT_writable_descriptor_tables); ++ if (mm->context.size*LDT_ENTRY_SIZE > PAGE_SIZE) ++ vfree(mm->context.ldt); ++ else ++ kfree(mm->context.ldt); ++ mm->context.size = 0; ++ } ++} ++ ++static int read_ldt(void __user * ptr, unsigned long bytecount) ++{ ++ int err; ++ unsigned long size; ++ struct mm_struct * mm = current->mm; ++ ++ if (!mm->context.size) ++ return 0; ++ if (bytecount > LDT_ENTRY_SIZE*LDT_ENTRIES) ++ bytecount = LDT_ENTRY_SIZE*LDT_ENTRIES; ++ ++ down(&mm->context.sem); ++ size = mm->context.size*LDT_ENTRY_SIZE; ++ if (size > bytecount) ++ size = bytecount; ++ ++ err = 0; ++ if (copy_to_user(ptr, mm->context.ldt, size)) ++ err = -EFAULT; ++ up(&mm->context.sem); ++ if (err < 0) ++ goto error_return; ++ if (size != bytecount) { ++ /* zero-fill the rest */ ++ if (clear_user(ptr+size, bytecount-size) != 0) { ++ err = -EFAULT; ++ goto error_return; ++ } ++ } ++ return bytecount; ++error_return: ++ return err; ++} ++ ++static int read_default_ldt(void __user * ptr, unsigned long bytecount) ++{ ++ int err; ++ unsigned long size; ++ void *address; ++ ++ err = 0; ++ address = &default_ldt[0]; ++ size = 5*sizeof(struct desc_struct); ++ if (size > bytecount) ++ size = bytecount; ++ ++ err = size; ++ if (copy_to_user(ptr, address, size)) ++ err = -EFAULT; ++ ++ return err; ++} ++ ++static int write_ldt(void __user * ptr, unsigned long bytecount, int oldmode) ++{ ++ struct mm_struct * mm = current->mm; ++ __u32 entry_1, entry_2; ++ int error; ++ struct user_desc ldt_info; ++ ++ error = -EINVAL; ++ if (bytecount != sizeof(ldt_info)) ++ goto out; ++ error = -EFAULT; ++ if (copy_from_user(&ldt_info, ptr, sizeof(ldt_info))) ++ goto out; ++ ++ error = -EINVAL; ++ if (ldt_info.entry_number >= LDT_ENTRIES) ++ goto out; ++ if (ldt_info.contents == 3) { ++ if (oldmode) ++ goto out; ++ if (ldt_info.seg_not_present == 0) ++ goto out; ++ } ++ ++ down(&mm->context.sem); ++ if (ldt_info.entry_number >= mm->context.size) { ++ error = alloc_ldt(¤t->mm->context, ldt_info.entry_number+1, 1); ++ if (error < 0) ++ goto out_unlock; ++ } ++ ++ /* Allow LDTs to be cleared by the user. */ ++ if (ldt_info.base_addr == 0 && ldt_info.limit == 0) { ++ if (oldmode || LDT_empty(&ldt_info)) { ++ entry_1 = 0; ++ entry_2 = 0; ++ goto install; ++ } ++ } ++ ++ entry_1 = LDT_entry_a(&ldt_info); ++ entry_2 = LDT_entry_b(&ldt_info); ++ if (oldmode) ++ entry_2 &= ~(1 << 20); ++ ++ /* Install the new entry ... */ ++install: ++ error = write_ldt_entry(mm->context.ldt, ldt_info.entry_number, ++ entry_1, entry_2); ++ ++out_unlock: ++ up(&mm->context.sem); ++out: ++ return error; ++} ++ ++asmlinkage int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount) ++{ ++ int ret = -ENOSYS; ++ ++ switch (func) { ++ case 0: ++ ret = read_ldt(ptr, bytecount); ++ break; ++ case 1: ++ ret = write_ldt(ptr, bytecount, 1); ++ break; ++ case 2: ++ ret = read_default_ldt(ptr, bytecount); ++ break; ++ case 0x11: ++ ret = write_ldt(ptr, bytecount, 0); ++ break; ++ } ++ return ret; ++} +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/arch/x86/kernel/microcode-xen.c 2007-06-12 13:12:48.000000000 +0200 +@@ -0,0 +1,144 @@ ++/* ++ * Intel CPU Microcode Update Driver for Linux ++ * ++ * Copyright (C) 2000-2004 Tigran Aivazian ++ * ++ * This driver allows to upgrade microcode on Intel processors ++ * belonging to IA-32 family - PentiumPro, Pentium II, ++ * Pentium III, Xeon, Pentium 4, etc. ++ * ++ * Reference: Section 8.10 of Volume III, Intel Pentium 4 Manual, ++ * Order Number 245472 or free download from: ++ * ++ * http://developer.intel.com/design/pentium4/manuals/245472.htm ++ * ++ * For more information, go to http://www.urbanmyth.org/microcode ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version ++ * 2 of the License, or (at your option) any later version. ++ */ ++ ++//#define DEBUG /* pr_debug */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++MODULE_DESCRIPTION("Intel CPU (IA-32) Microcode Update Driver"); ++MODULE_AUTHOR("Tigran Aivazian "); ++MODULE_LICENSE("GPL"); ++ ++static int verbose; ++module_param(verbose, int, 0644); ++ ++#define MICROCODE_VERSION "1.14a-xen" ++ ++#define DEFAULT_UCODE_DATASIZE (2000) /* 2000 bytes */ ++#define MC_HEADER_SIZE (sizeof (microcode_header_t)) /* 48 bytes */ ++#define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) /* 2048 bytes */ ++ ++/* no concurrent ->write()s are allowed on /dev/cpu/microcode */ ++static DEFINE_MUTEX(microcode_mutex); ++ ++static int microcode_open (struct inode *unused1, struct file *unused2) ++{ ++ return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; ++} ++ ++ ++static int do_microcode_update (const void __user *ubuf, size_t len) ++{ ++ int err; ++ void *kbuf; ++ ++ kbuf = vmalloc(len); ++ if (!kbuf) ++ return -ENOMEM; ++ ++ if (copy_from_user(kbuf, ubuf, len) == 0) { ++ struct xen_platform_op op; ++ ++ op.cmd = XENPF_microcode_update; ++ set_xen_guest_handle(op.u.microcode.data, kbuf); ++ op.u.microcode.length = len; ++ err = HYPERVISOR_platform_op(&op); ++ } else ++ err = -EFAULT; ++ ++ vfree(kbuf); ++ ++ return err; ++} ++ ++static ssize_t microcode_write (struct file *file, const char __user *buf, size_t len, loff_t *ppos) ++{ ++ ssize_t ret; ++ ++ if (len < MC_HEADER_SIZE) { ++ printk(KERN_ERR "microcode: not enough data\n"); ++ return -EINVAL; ++ } ++ ++ mutex_lock(µcode_mutex); ++ ++ ret = do_microcode_update(buf, len); ++ if (!ret) ++ ret = (ssize_t)len; ++ ++ mutex_unlock(µcode_mutex); ++ ++ return ret; ++} ++ ++static struct file_operations microcode_fops = { ++ .owner = THIS_MODULE, ++ .write = microcode_write, ++ .open = microcode_open, ++}; ++ ++static struct miscdevice microcode_dev = { ++ .minor = MICROCODE_MINOR, ++ .name = "microcode", ++ .fops = µcode_fops, ++}; ++ ++static int __init microcode_init (void) ++{ ++ int error; ++ ++ error = misc_register(µcode_dev); ++ if (error) { ++ printk(KERN_ERR ++ "microcode: can't misc_register on minor=%d\n", ++ MICROCODE_MINOR); ++ return error; ++ } ++ ++ printk(KERN_INFO ++ "IA-32 Microcode Update Driver: v" MICROCODE_VERSION " \n"); ++ return 0; ++} ++ ++static void __exit microcode_exit (void) ++{ ++ misc_deregister(µcode_dev); ++} ++ ++module_init(microcode_init) ++module_exit(microcode_exit) ++MODULE_ALIAS_MISCDEV(MICROCODE_MINOR); +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/arch/x86/kernel/mpparse_32-xen.c 2007-06-12 13:12:48.000000000 +0200 +@@ -0,0 +1,1185 @@ ++/* ++ * Intel Multiprocessor Specification 1.1 and 1.4 ++ * compliant MP-table parsing routines. ++ * ++ * (c) 1995 Alan Cox, Building #3 ++ * (c) 1998, 1999, 2000 Ingo Molnar ++ * ++ * Fixes ++ * Erich Boleyn : MP v1.4 and additional changes. ++ * Alan Cox : Added EBDA scanning ++ * Ingo Molnar : various cleanups and rewrites ++ * Maciej W. Rozycki: Bits for default MP configurations ++ * Paul Diefenbaugh: Added full ACPI support ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++/* Have we found an MP table */ ++int smp_found_config; ++unsigned int __initdata maxcpus = NR_CPUS; ++ ++/* ++ * Various Linux-internal data structures created from the ++ * MP-table. ++ */ ++int apic_version [MAX_APICS]; ++int mp_bus_id_to_type [MAX_MP_BUSSES]; ++int mp_bus_id_to_node [MAX_MP_BUSSES]; ++int mp_bus_id_to_local [MAX_MP_BUSSES]; ++int quad_local_to_mp_bus_id [NR_CPUS/4][4]; ++int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 }; ++static int mp_current_pci_id; ++ ++/* I/O APIC entries */ ++struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS]; ++ ++/* # of MP IRQ source entries */ ++struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES]; ++ ++/* MP IRQ source entries */ ++int mp_irq_entries; ++ ++int nr_ioapics; ++ ++int pic_mode; ++unsigned long mp_lapic_addr; ++ ++unsigned int def_to_bigsmp = 0; ++ ++/* Processor that is doing the boot up */ ++unsigned int boot_cpu_physical_apicid = -1U; ++/* Internal processor count */ ++static unsigned int __devinitdata num_processors; ++ ++/* Bitmask of physically existing CPUs */ ++physid_mask_t phys_cpu_present_map; ++ ++u8 bios_cpu_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID }; ++ ++/* ++ * Intel MP BIOS table parsing routines: ++ */ ++ ++ ++/* ++ * Checksum an MP configuration block. ++ */ ++ ++static int __init mpf_checksum(unsigned char *mp, int len) ++{ ++ int sum = 0; ++ ++ while (len--) ++ sum += *mp++; ++ ++ return sum & 0xFF; ++} ++ ++/* ++ * Have to match translation table entries to main table entries by counter ++ * hence the mpc_record variable .... can't see a less disgusting way of ++ * doing this .... ++ */ ++ ++static int mpc_record; ++static struct mpc_config_translation *translation_table[MAX_MPC_ENTRY] __initdata; ++ ++#ifndef CONFIG_XEN ++static void __devinit MP_processor_info (struct mpc_config_processor *m) ++{ ++ int ver, apicid; ++ physid_mask_t phys_cpu; ++ ++ if (!(m->mpc_cpuflag & CPU_ENABLED)) ++ return; ++ ++ apicid = mpc_apic_id(m, translation_table[mpc_record]); ++ ++ if (m->mpc_featureflag&(1<<0)) ++ Dprintk(" Floating point unit present.\n"); ++ if (m->mpc_featureflag&(1<<7)) ++ Dprintk(" Machine Exception supported.\n"); ++ if (m->mpc_featureflag&(1<<8)) ++ Dprintk(" 64 bit compare & exchange supported.\n"); ++ if (m->mpc_featureflag&(1<<9)) ++ Dprintk(" Internal APIC present.\n"); ++ if (m->mpc_featureflag&(1<<11)) ++ Dprintk(" SEP present.\n"); ++ if (m->mpc_featureflag&(1<<12)) ++ Dprintk(" MTRR present.\n"); ++ if (m->mpc_featureflag&(1<<13)) ++ Dprintk(" PGE present.\n"); ++ if (m->mpc_featureflag&(1<<14)) ++ Dprintk(" MCA present.\n"); ++ if (m->mpc_featureflag&(1<<15)) ++ Dprintk(" CMOV present.\n"); ++ if (m->mpc_featureflag&(1<<16)) ++ Dprintk(" PAT present.\n"); ++ if (m->mpc_featureflag&(1<<17)) ++ Dprintk(" PSE present.\n"); ++ if (m->mpc_featureflag&(1<<18)) ++ Dprintk(" PSN present.\n"); ++ if (m->mpc_featureflag&(1<<19)) ++ Dprintk(" Cache Line Flush Instruction present.\n"); ++ /* 20 Reserved */ ++ if (m->mpc_featureflag&(1<<21)) ++ Dprintk(" Debug Trace and EMON Store present.\n"); ++ if (m->mpc_featureflag&(1<<22)) ++ Dprintk(" ACPI Thermal Throttle Registers present.\n"); ++ if (m->mpc_featureflag&(1<<23)) ++ Dprintk(" MMX present.\n"); ++ if (m->mpc_featureflag&(1<<24)) ++ Dprintk(" FXSR present.\n"); ++ if (m->mpc_featureflag&(1<<25)) ++ Dprintk(" XMM present.\n"); ++ if (m->mpc_featureflag&(1<<26)) ++ Dprintk(" Willamette New Instructions present.\n"); ++ if (m->mpc_featureflag&(1<<27)) ++ Dprintk(" Self Snoop present.\n"); ++ if (m->mpc_featureflag&(1<<28)) ++ Dprintk(" HT present.\n"); ++ if (m->mpc_featureflag&(1<<29)) ++ Dprintk(" Thermal Monitor present.\n"); ++ /* 30, 31 Reserved */ ++ ++ ++ if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) { ++ Dprintk(" Bootup CPU\n"); ++ boot_cpu_physical_apicid = m->mpc_apicid; ++ } ++ ++ ver = m->mpc_apicver; ++ ++ /* ++ * Validate version ++ */ ++ if (ver == 0x0) { ++ printk(KERN_WARNING "BIOS bug, APIC version is 0 for CPU#%d! " ++ "fixing up to 0x10. (tell your hw vendor)\n", ++ m->mpc_apicid); ++ ver = 0x10; ++ } ++ apic_version[m->mpc_apicid] = ver; ++ ++ phys_cpu = apicid_to_cpu_present(apicid); ++ physids_or(phys_cpu_present_map, phys_cpu_present_map, phys_cpu); ++ ++ if (num_processors >= NR_CPUS) { ++ printk(KERN_WARNING "WARNING: NR_CPUS limit of %i reached." ++ " Processor ignored.\n", NR_CPUS); ++ return; ++ } ++ ++ if (num_processors >= maxcpus) { ++ printk(KERN_WARNING "WARNING: maxcpus limit of %i reached." ++ " Processor ignored.\n", maxcpus); ++ return; ++ } ++ ++ cpu_set(num_processors, cpu_possible_map); ++ num_processors++; ++ ++ /* ++ * Would be preferable to switch to bigsmp when CONFIG_HOTPLUG_CPU=y ++ * but we need to work other dependencies like SMP_SUSPEND etc ++ * before this can be done without some confusion. ++ * if (CPU_HOTPLUG_ENABLED || num_processors > 8) ++ * - Ashok Raj ++ */ ++ if (num_processors > 8) { ++ switch (boot_cpu_data.x86_vendor) { ++ case X86_VENDOR_INTEL: ++ if (!APIC_XAPIC(ver)) { ++ def_to_bigsmp = 0; ++ break; ++ } ++ /* If P4 and above fall through */ ++ case X86_VENDOR_AMD: ++ def_to_bigsmp = 1; ++ } ++ } ++ bios_cpu_apicid[num_processors - 1] = m->mpc_apicid; ++} ++#else ++void __init MP_processor_info (struct mpc_config_processor *m) ++{ ++ num_processors++; ++} ++#endif /* CONFIG_XEN */ ++ ++static void __init MP_bus_info (struct mpc_config_bus *m) ++{ ++ char str[7]; ++ ++ memcpy(str, m->mpc_bustype, 6); ++ str[6] = 0; ++ ++ mpc_oem_bus_info(m, str, translation_table[mpc_record]); ++ ++ if (m->mpc_busid >= MAX_MP_BUSSES) { ++ printk(KERN_WARNING "MP table busid value (%d) for bustype %s " ++ " is too large, max. supported is %d\n", ++ m->mpc_busid, str, MAX_MP_BUSSES - 1); ++ return; ++ } ++ ++ if (strncmp(str, BUSTYPE_ISA, sizeof(BUSTYPE_ISA)-1) == 0) { ++ mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA; ++ } else if (strncmp(str, BUSTYPE_EISA, sizeof(BUSTYPE_EISA)-1) == 0) { ++ mp_bus_id_to_type[m->mpc_busid] = MP_BUS_EISA; ++ } else if (strncmp(str, BUSTYPE_PCI, sizeof(BUSTYPE_PCI)-1) == 0) { ++ mpc_oem_pci_bus(m, translation_table[mpc_record]); ++ mp_bus_id_to_type[m->mpc_busid] = MP_BUS_PCI; ++ mp_bus_id_to_pci_bus[m->mpc_busid] = mp_current_pci_id; ++ mp_current_pci_id++; ++ } else if (strncmp(str, BUSTYPE_MCA, sizeof(BUSTYPE_MCA)-1) == 0) { ++ mp_bus_id_to_type[m->mpc_busid] = MP_BUS_MCA; ++ } else if (strncmp(str, BUSTYPE_NEC98, sizeof(BUSTYPE_NEC98)-1) == 0) { ++ mp_bus_id_to_type[m->mpc_busid] = MP_BUS_NEC98; ++ } else { ++ printk(KERN_WARNING "Unknown bustype %s - ignoring\n", str); ++ } ++} ++ ++static void __init MP_ioapic_info (struct mpc_config_ioapic *m) ++{ ++ if (!(m->mpc_flags & MPC_APIC_USABLE)) ++ return; ++ ++ printk(KERN_INFO "I/O APIC #%d Version %d at 0x%lX.\n", ++ m->mpc_apicid, m->mpc_apicver, m->mpc_apicaddr); ++ if (nr_ioapics >= MAX_IO_APICS) { ++ printk(KERN_CRIT "Max # of I/O APICs (%d) exceeded (found %d).\n", ++ MAX_IO_APICS, nr_ioapics); ++ panic("Recompile kernel with bigger MAX_IO_APICS!.\n"); ++ } ++ if (!m->mpc_apicaddr) { ++ printk(KERN_ERR "WARNING: bogus zero I/O APIC address" ++ " found in MP table, skipping!\n"); ++ return; ++ } ++ mp_ioapics[nr_ioapics] = *m; ++ nr_ioapics++; ++} ++ ++static void __init MP_intsrc_info (struct mpc_config_intsrc *m) ++{ ++ mp_irqs [mp_irq_entries] = *m; ++ Dprintk("Int: type %d, pol %d, trig %d, bus %d," ++ " IRQ %02x, APIC ID %x, APIC INT %02x\n", ++ m->mpc_irqtype, m->mpc_irqflag & 3, ++ (m->mpc_irqflag >> 2) & 3, m->mpc_srcbus, ++ m->mpc_srcbusirq, m->mpc_dstapic, m->mpc_dstirq); ++ if (++mp_irq_entries == MAX_IRQ_SOURCES) ++ panic("Max # of irq sources exceeded!!\n"); ++} ++ ++static void __init MP_lintsrc_info (struct mpc_config_lintsrc *m) ++{ ++ Dprintk("Lint: type %d, pol %d, trig %d, bus %d," ++ " IRQ %02x, APIC ID %x, APIC LINT %02x\n", ++ m->mpc_irqtype, m->mpc_irqflag & 3, ++ (m->mpc_irqflag >> 2) &3, m->mpc_srcbusid, ++ m->mpc_srcbusirq, m->mpc_destapic, m->mpc_destapiclint); ++ /* ++ * Well it seems all SMP boards in existence ++ * use ExtINT/LVT1 == LINT0 and ++ * NMI/LVT2 == LINT1 - the following check ++ * will show us if this assumptions is false. ++ * Until then we do not have to add baggage. ++ */ ++ if ((m->mpc_irqtype == mp_ExtINT) && ++ (m->mpc_destapiclint != 0)) ++ BUG(); ++ if ((m->mpc_irqtype == mp_NMI) && ++ (m->mpc_destapiclint != 1)) ++ BUG(); ++} ++ ++#ifdef CONFIG_X86_NUMAQ ++static void __init MP_translation_info (struct mpc_config_translation *m) ++{ ++ printk(KERN_INFO "Translation: record %d, type %d, quad %d, global %d, local %d\n", mpc_record, m->trans_type, m->trans_quad, m->trans_global, m->trans_local); ++ ++ if (mpc_record >= MAX_MPC_ENTRY) ++ printk(KERN_ERR "MAX_MPC_ENTRY exceeded!\n"); ++ else ++ translation_table[mpc_record] = m; /* stash this for later */ ++ if (m->trans_quad < MAX_NUMNODES && !node_online(m->trans_quad)) ++ node_set_online(m->trans_quad); ++} ++ ++/* ++ * Read/parse the MPC oem tables ++ */ ++ ++static void __init smp_read_mpc_oem(struct mp_config_oemtable *oemtable, \ ++ unsigned short oemsize) ++{ ++ int count = sizeof (*oemtable); /* the header size */ ++ unsigned char *oemptr = ((unsigned char *)oemtable)+count; ++ ++ mpc_record = 0; ++ printk(KERN_INFO "Found an OEM MPC table at %8p - parsing it ... \n", oemtable); ++ if (memcmp(oemtable->oem_signature,MPC_OEM_SIGNATURE,4)) ++ { ++ printk(KERN_WARNING "SMP mpc oemtable: bad signature [%c%c%c%c]!\n", ++ oemtable->oem_signature[0], ++ oemtable->oem_signature[1], ++ oemtable->oem_signature[2], ++ oemtable->oem_signature[3]); ++ return; ++ } ++ if (mpf_checksum((unsigned char *)oemtable,oemtable->oem_length)) ++ { ++ printk(KERN_WARNING "SMP oem mptable: checksum error!\n"); ++ return; ++ } ++ while (count < oemtable->oem_length) { ++ switch (*oemptr) { ++ case MP_TRANSLATION: ++ { ++ struct mpc_config_translation *m= ++ (struct mpc_config_translation *)oemptr; ++ MP_translation_info(m); ++ oemptr += sizeof(*m); ++ count += sizeof(*m); ++ ++mpc_record; ++ break; ++ } ++ default: ++ { ++ printk(KERN_WARNING "Unrecognised OEM table entry type! - %d\n", (int) *oemptr); ++ return; ++ } ++ } ++ } ++} ++ ++static inline void mps_oem_check(struct mp_config_table *mpc, char *oem, ++ char *productid) ++{ ++ if (strncmp(oem, "IBM NUMA", 8)) ++ printk("Warning! May not be a NUMA-Q system!\n"); ++ if (mpc->mpc_oemptr) ++ smp_read_mpc_oem((struct mp_config_oemtable *) mpc->mpc_oemptr, ++ mpc->mpc_oemsize); ++} ++#endif /* CONFIG_X86_NUMAQ */ ++ ++/* ++ * Read/parse the MPC ++ */ ++ ++static int __init smp_read_mpc(struct mp_config_table *mpc) ++{ ++ char str[16]; ++ char oem[10]; ++ int count=sizeof(*mpc); ++ unsigned char *mpt=((unsigned char *)mpc)+count; ++ ++ if (memcmp(mpc->mpc_signature,MPC_SIGNATURE,4)) { ++ printk(KERN_ERR "SMP mptable: bad signature [0x%x]!\n", ++ *(u32 *)mpc->mpc_signature); ++ return 0; ++ } ++ if (mpf_checksum((unsigned char *)mpc,mpc->mpc_length)) { ++ printk(KERN_ERR "SMP mptable: checksum error!\n"); ++ return 0; ++ } ++ if (mpc->mpc_spec!=0x01 && mpc->mpc_spec!=0x04) { ++ printk(KERN_ERR "SMP mptable: bad table version (%d)!!\n", ++ mpc->mpc_spec); ++ return 0; ++ } ++ if (!mpc->mpc_lapic) { ++ printk(KERN_ERR "SMP mptable: null local APIC address!\n"); ++ return 0; ++ } ++ memcpy(oem,mpc->mpc_oem,8); ++ oem[8]=0; ++ printk(KERN_INFO "OEM ID: %s ",oem); ++ ++ memcpy(str,mpc->mpc_productid,12); ++ str[12]=0; ++ printk("Product ID: %s ",str); ++ ++ mps_oem_check(mpc, oem, str); ++ ++ printk("APIC at: 0x%lX\n",mpc->mpc_lapic); ++ ++ /* ++ * Save the local APIC address (it might be non-default) -- but only ++ * if we're not using ACPI. ++ */ ++ if (!acpi_lapic) ++ mp_lapic_addr = mpc->mpc_lapic; ++ ++ /* ++ * Now process the configuration blocks. ++ */ ++ mpc_record = 0; ++ while (count < mpc->mpc_length) { ++ switch(*mpt) { ++ case MP_PROCESSOR: ++ { ++ struct mpc_config_processor *m= ++ (struct mpc_config_processor *)mpt; ++ /* ACPI may have already provided this data */ ++ if (!acpi_lapic) ++ MP_processor_info(m); ++ mpt += sizeof(*m); ++ count += sizeof(*m); ++ break; ++ } ++ case MP_BUS: ++ { ++ struct mpc_config_bus *m= ++ (struct mpc_config_bus *)mpt; ++ MP_bus_info(m); ++ mpt += sizeof(*m); ++ count += sizeof(*m); ++ break; ++ } ++ case MP_IOAPIC: ++ { ++ struct mpc_config_ioapic *m= ++ (struct mpc_config_ioapic *)mpt; ++ MP_ioapic_info(m); ++ mpt+=sizeof(*m); ++ count+=sizeof(*m); ++ break; ++ } ++ case MP_INTSRC: ++ { ++ struct mpc_config_intsrc *m= ++ (struct mpc_config_intsrc *)mpt; ++ ++ MP_intsrc_info(m); ++ mpt+=sizeof(*m); ++ count+=sizeof(*m); ++ break; ++ } ++ case MP_LINTSRC: ++ { ++ struct mpc_config_lintsrc *m= ++ (struct mpc_config_lintsrc *)mpt; ++ MP_lintsrc_info(m); ++ mpt+=sizeof(*m); ++ count+=sizeof(*m); ++ break; ++ } ++ default: ++ { ++ count = mpc->mpc_length; ++ break; ++ } ++ } ++ ++mpc_record; ++ } ++ clustered_apic_check(); ++ if (!num_processors) ++ printk(KERN_ERR "SMP mptable: no processors registered!\n"); ++ return num_processors; ++} ++ ++static int __init ELCR_trigger(unsigned int irq) ++{ ++ unsigned int port; ++ ++ port = 0x4d0 + (irq >> 3); ++ return (inb(port) >> (irq & 7)) & 1; ++} ++ ++static void __init construct_default_ioirq_mptable(int mpc_default_type) ++{ ++ struct mpc_config_intsrc intsrc; ++ int i; ++ int ELCR_fallback = 0; ++ ++ intsrc.mpc_type = MP_INTSRC; ++ intsrc.mpc_irqflag = 0; /* conforming */ ++ intsrc.mpc_srcbus = 0; ++ intsrc.mpc_dstapic = mp_ioapics[0].mpc_apicid; ++ ++ intsrc.mpc_irqtype = mp_INT; ++ ++ /* ++ * If true, we have an ISA/PCI system with no IRQ entries ++ * in the MP table. To prevent the PCI interrupts from being set up ++ * incorrectly, we try to use the ELCR. The sanity check to see if ++ * there is good ELCR data is very simple - IRQ0, 1, 2 and 13 can ++ * never be level sensitive, so we simply see if the ELCR agrees. ++ * If it does, we assume it's valid. ++ */ ++ if (mpc_default_type == 5) { ++ printk(KERN_INFO "ISA/PCI bus type with no IRQ information... falling back to ELCR\n"); ++ ++ if (ELCR_trigger(0) || ELCR_trigger(1) || ELCR_trigger(2) || ELCR_trigger(13)) ++ printk(KERN_WARNING "ELCR contains invalid data... not using ELCR\n"); ++ else { ++ printk(KERN_INFO "Using ELCR to identify PCI interrupts\n"); ++ ELCR_fallback = 1; ++ } ++ } ++ ++ for (i = 0; i < 16; i++) { ++ switch (mpc_default_type) { ++ case 2: ++ if (i == 0 || i == 13) ++ continue; /* IRQ0 & IRQ13 not connected */ ++ /* fall through */ ++ default: ++ if (i == 2) ++ continue; /* IRQ2 is never connected */ ++ } ++ ++ if (ELCR_fallback) { ++ /* ++ * If the ELCR indicates a level-sensitive interrupt, we ++ * copy that information over to the MP table in the ++ * irqflag field (level sensitive, active high polarity). ++ */ ++ if (ELCR_trigger(i)) ++ intsrc.mpc_irqflag = 13; ++ else ++ intsrc.mpc_irqflag = 0; ++ } ++ ++ intsrc.mpc_srcbusirq = i; ++ intsrc.mpc_dstirq = i ? i : 2; /* IRQ0 to INTIN2 */ ++ MP_intsrc_info(&intsrc); ++ } ++ ++ intsrc.mpc_irqtype = mp_ExtINT; ++ intsrc.mpc_srcbusirq = 0; ++ intsrc.mpc_dstirq = 0; /* 8259A to INTIN0 */ ++ MP_intsrc_info(&intsrc); ++} ++ ++static inline void __init construct_default_ISA_mptable(int mpc_default_type) ++{ ++ struct mpc_config_processor processor; ++ struct mpc_config_bus bus; ++ struct mpc_config_ioapic ioapic; ++ struct mpc_config_lintsrc lintsrc; ++ int linttypes[2] = { mp_ExtINT, mp_NMI }; ++ int i; ++ ++ /* ++ * local APIC has default address ++ */ ++ mp_lapic_addr = APIC_DEFAULT_PHYS_BASE; ++ ++ /* ++ * 2 CPUs, numbered 0 & 1. ++ */ ++ processor.mpc_type = MP_PROCESSOR; ++ /* Either an integrated APIC or a discrete 82489DX. */ ++ processor.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01; ++ processor.mpc_cpuflag = CPU_ENABLED; ++ processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) | ++ (boot_cpu_data.x86_model << 4) | ++ boot_cpu_data.x86_mask; ++ processor.mpc_featureflag = boot_cpu_data.x86_capability[0]; ++ processor.mpc_reserved[0] = 0; ++ processor.mpc_reserved[1] = 0; ++ for (i = 0; i < 2; i++) { ++ processor.mpc_apicid = i; ++ MP_processor_info(&processor); ++ } ++ ++ bus.mpc_type = MP_BUS; ++ bus.mpc_busid = 0; ++ switch (mpc_default_type) { ++ default: ++ printk("???\n"); ++ printk(KERN_ERR "Unknown standard configuration %d\n", ++ mpc_default_type); ++ /* fall through */ ++ case 1: ++ case 5: ++ memcpy(bus.mpc_bustype, "ISA ", 6); ++ break; ++ case 2: ++ case 6: ++ case 3: ++ memcpy(bus.mpc_bustype, "EISA ", 6); ++ break; ++ case 4: ++ case 7: ++ memcpy(bus.mpc_bustype, "MCA ", 6); ++ } ++ MP_bus_info(&bus); ++ if (mpc_default_type > 4) { ++ bus.mpc_busid = 1; ++ memcpy(bus.mpc_bustype, "PCI ", 6); ++ MP_bus_info(&bus); ++ } ++ ++ ioapic.mpc_type = MP_IOAPIC; ++ ioapic.mpc_apicid = 2; ++ ioapic.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01; ++ ioapic.mpc_flags = MPC_APIC_USABLE; ++ ioapic.mpc_apicaddr = 0xFEC00000; ++ MP_ioapic_info(&ioapic); ++ ++ /* ++ * We set up most of the low 16 IO-APIC pins according to MPS rules. ++ */ ++ construct_default_ioirq_mptable(mpc_default_type); ++ ++ lintsrc.mpc_type = MP_LINTSRC; ++ lintsrc.mpc_irqflag = 0; /* conforming */ ++ lintsrc.mpc_srcbusid = 0; ++ lintsrc.mpc_srcbusirq = 0; ++ lintsrc.mpc_destapic = MP_APIC_ALL; ++ for (i = 0; i < 2; i++) { ++ lintsrc.mpc_irqtype = linttypes[i]; ++ lintsrc.mpc_destapiclint = i; ++ MP_lintsrc_info(&lintsrc); ++ } ++} ++ ++static struct intel_mp_floating *mpf_found; ++ ++/* ++ * Scan the memory blocks for an SMP configuration block. ++ */ ++void __init get_smp_config (void) ++{ ++ struct intel_mp_floating *mpf = mpf_found; ++ ++ /* ++ * ACPI supports both logical (e.g. Hyper-Threading) and physical ++ * processors, where MPS only supports physical. ++ */ ++ if (acpi_lapic && acpi_ioapic) { ++ printk(KERN_INFO "Using ACPI (MADT) for SMP configuration information\n"); ++ return; ++ } ++ else if (acpi_lapic) ++ printk(KERN_INFO "Using ACPI for processor (LAPIC) configuration information\n"); ++ ++ printk(KERN_INFO "Intel MultiProcessor Specification v1.%d\n", mpf->mpf_specification); ++ if (mpf->mpf_feature2 & (1<<7)) { ++ printk(KERN_INFO " IMCR and PIC compatibility mode.\n"); ++ pic_mode = 1; ++ } else { ++ printk(KERN_INFO " Virtual Wire compatibility mode.\n"); ++ pic_mode = 0; ++ } ++ ++ /* ++ * Now see if we need to read further. ++ */ ++ if (mpf->mpf_feature1 != 0) { ++ ++ printk(KERN_INFO "Default MP configuration #%d\n", mpf->mpf_feature1); ++ construct_default_ISA_mptable(mpf->mpf_feature1); ++ ++ } else if (mpf->mpf_physptr) { ++ ++ /* ++ * Read the physical hardware table. Anything here will ++ * override the defaults. ++ */ ++ if (!smp_read_mpc(isa_bus_to_virt(mpf->mpf_physptr))) { ++ smp_found_config = 0; ++ printk(KERN_ERR "BIOS bug, MP table errors detected!...\n"); ++ printk(KERN_ERR "... disabling SMP support. (tell your hw vendor)\n"); ++ return; ++ } ++ /* ++ * If there are no explicit MP IRQ entries, then we are ++ * broken. We set up most of the low 16 IO-APIC pins to ++ * ISA defaults and hope it will work. ++ */ ++ if (!mp_irq_entries) { ++ struct mpc_config_bus bus; ++ ++ printk(KERN_ERR "BIOS bug, no explicit IRQ entries, using default mptable. (tell your hw vendor)\n"); ++ ++ bus.mpc_type = MP_BUS; ++ bus.mpc_busid = 0; ++ memcpy(bus.mpc_bustype, "ISA ", 6); ++ MP_bus_info(&bus); ++ ++ construct_default_ioirq_mptable(0); ++ } ++ ++ } else ++ BUG(); ++ ++ printk(KERN_INFO "Processors: %d\n", num_processors); ++ /* ++ * Only use the first configuration found. ++ */ ++} ++ ++static int __init smp_scan_config (unsigned long base, unsigned long length) ++{ ++ unsigned long *bp = isa_bus_to_virt(base); ++ struct intel_mp_floating *mpf; ++ ++ Dprintk("Scan SMP from %p for %ld bytes.\n", bp,length); ++ if (sizeof(*mpf) != 16) ++ printk("Error: MPF size\n"); ++ ++ while (length > 0) { ++ mpf = (struct intel_mp_floating *)bp; ++ if ((*bp == SMP_MAGIC_IDENT) && ++ (mpf->mpf_length == 1) && ++ !mpf_checksum((unsigned char *)bp, 16) && ++ ((mpf->mpf_specification == 1) ++ || (mpf->mpf_specification == 4)) ) { ++ ++ smp_found_config = 1; ++#ifndef CONFIG_XEN ++ printk(KERN_INFO "found SMP MP-table at %08lx\n", ++ virt_to_phys(mpf)); ++ reserve_bootmem(virt_to_phys(mpf), PAGE_SIZE); ++ if (mpf->mpf_physptr) { ++ /* ++ * We cannot access to MPC table to compute ++ * table size yet, as only few megabytes from ++ * the bottom is mapped now. ++ * PC-9800's MPC table places on the very last ++ * of physical memory; so that simply reserving ++ * PAGE_SIZE from mpg->mpf_physptr yields BUG() ++ * in reserve_bootmem. ++ */ ++ unsigned long size = PAGE_SIZE; ++ unsigned long end = max_low_pfn * PAGE_SIZE; ++ if (mpf->mpf_physptr + size > end) ++ size = end - mpf->mpf_physptr; ++ reserve_bootmem(mpf->mpf_physptr, size); ++ } ++#else ++ printk(KERN_INFO "found SMP MP-table at %08lx\n", ++ ((unsigned long)bp - (unsigned long)isa_bus_to_virt(base)) + base); ++#endif ++ ++ mpf_found = mpf; ++ return 1; ++ } ++ bp += 4; ++ length -= 16; ++ } ++ return 0; ++} ++ ++void __init find_smp_config (void) ++{ ++#ifndef CONFIG_XEN ++ unsigned int address; ++#endif ++ ++ /* ++ * FIXME: Linux assumes you have 640K of base ram.. ++ * this continues the error... ++ * ++ * 1) Scan the bottom 1K for a signature ++ * 2) Scan the top 1K of base RAM ++ * 3) Scan the 64K of bios ++ */ ++ if (smp_scan_config(0x0,0x400) || ++ smp_scan_config(639*0x400,0x400) || ++ smp_scan_config(0xF0000,0x10000)) ++ return; ++ /* ++ * If it is an SMP machine we should know now, unless the ++ * configuration is in an EISA/MCA bus machine with an ++ * extended bios data area. ++ * ++ * there is a real-mode segmented pointer pointing to the ++ * 4K EBDA area at 0x40E, calculate and scan it here. ++ * ++ * NOTE! There are Linux loaders that will corrupt the EBDA ++ * area, and as such this kind of SMP config may be less ++ * trustworthy, simply because the SMP table may have been ++ * stomped on during early boot. These loaders are buggy and ++ * should be fixed. ++ * ++ * MP1.4 SPEC states to only scan first 1K of 4K EBDA. ++ */ ++ ++#ifndef CONFIG_XEN ++ address = get_bios_ebda(); ++ if (address) ++ smp_scan_config(address, 0x400); ++#endif ++} ++ ++int es7000_plat; ++ ++/* -------------------------------------------------------------------------- ++ ACPI-based MP Configuration ++ -------------------------------------------------------------------------- */ ++ ++#ifdef CONFIG_ACPI ++ ++void __init mp_register_lapic_address ( ++ u64 address) ++{ ++#ifndef CONFIG_XEN ++ mp_lapic_addr = (unsigned long) address; ++ ++ set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr); ++ ++ if (boot_cpu_physical_apicid == -1U) ++ boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID)); ++ ++ Dprintk("Boot CPU = %d\n", boot_cpu_physical_apicid); ++#endif ++} ++ ++ ++void __devinit mp_register_lapic ( ++ u8 id, ++ u8 enabled) ++{ ++ struct mpc_config_processor processor; ++ int boot_cpu = 0; ++ ++ if (MAX_APICS - id <= 0) { ++ printk(KERN_WARNING "Processor #%d invalid (max %d)\n", ++ id, MAX_APICS); ++ return; ++ } ++ ++ if (id == boot_cpu_physical_apicid) ++ boot_cpu = 1; ++ ++#ifndef CONFIG_XEN ++ processor.mpc_type = MP_PROCESSOR; ++ processor.mpc_apicid = id; ++ processor.mpc_apicver = GET_APIC_VERSION(apic_read(APIC_LVR)); ++ processor.mpc_cpuflag = (enabled ? CPU_ENABLED : 0); ++ processor.mpc_cpuflag |= (boot_cpu ? CPU_BOOTPROCESSOR : 0); ++ processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) | ++ (boot_cpu_data.x86_model << 4) | boot_cpu_data.x86_mask; ++ processor.mpc_featureflag = boot_cpu_data.x86_capability[0]; ++ processor.mpc_reserved[0] = 0; ++ processor.mpc_reserved[1] = 0; ++#endif ++ ++ MP_processor_info(&processor); ++} ++ ++#ifdef CONFIG_X86_IO_APIC ++ ++#define MP_ISA_BUS 0 ++#define MP_MAX_IOAPIC_PIN 127 ++ ++static struct mp_ioapic_routing { ++ int apic_id; ++ int gsi_base; ++ int gsi_end; ++ u32 pin_programmed[4]; ++} mp_ioapic_routing[MAX_IO_APICS]; ++ ++ ++static int mp_find_ioapic ( ++ int gsi) ++{ ++ int i = 0; ++ ++ /* Find the IOAPIC that manages this GSI. */ ++ for (i = 0; i < nr_ioapics; i++) { ++ if ((gsi >= mp_ioapic_routing[i].gsi_base) ++ && (gsi <= mp_ioapic_routing[i].gsi_end)) ++ return i; ++ } ++ ++ printk(KERN_ERR "ERROR: Unable to locate IOAPIC for GSI %d\n", gsi); ++ ++ return -1; ++} ++ ++ ++void __init mp_register_ioapic ( ++ u8 id, ++ u32 address, ++ u32 gsi_base) ++{ ++ int idx = 0; ++ int tmpid; ++ ++ if (nr_ioapics >= MAX_IO_APICS) { ++ printk(KERN_ERR "ERROR: Max # of I/O APICs (%d) exceeded " ++ "(found %d)\n", MAX_IO_APICS, nr_ioapics); ++ panic("Recompile kernel with bigger MAX_IO_APICS!\n"); ++ } ++ if (!address) { ++ printk(KERN_ERR "WARNING: Bogus (zero) I/O APIC address" ++ " found in MADT table, skipping!\n"); ++ return; ++ } ++ ++ idx = nr_ioapics++; ++ ++ mp_ioapics[idx].mpc_type = MP_IOAPIC; ++ mp_ioapics[idx].mpc_flags = MPC_APIC_USABLE; ++ mp_ioapics[idx].mpc_apicaddr = address; ++ ++#ifndef CONFIG_XEN ++ set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address); ++#endif ++ if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) ++ && !APIC_XAPIC(apic_version[boot_cpu_physical_apicid])) ++ tmpid = io_apic_get_unique_id(idx, id); ++ else ++ tmpid = id; ++ if (tmpid == -1) { ++ nr_ioapics--; ++ return; ++ } ++ mp_ioapics[idx].mpc_apicid = tmpid; ++ mp_ioapics[idx].mpc_apicver = io_apic_get_version(idx); ++ ++ /* ++ * Build basic GSI lookup table to facilitate gsi->io_apic lookups ++ * and to prevent reprogramming of IOAPIC pins (PCI GSIs). ++ */ ++ mp_ioapic_routing[idx].apic_id = mp_ioapics[idx].mpc_apicid; ++ mp_ioapic_routing[idx].gsi_base = gsi_base; ++ mp_ioapic_routing[idx].gsi_end = gsi_base + ++ io_apic_get_redir_entries(idx); ++ ++ printk("IOAPIC[%d]: apic_id %d, version %d, address 0x%lx, " ++ "GSI %d-%d\n", idx, mp_ioapics[idx].mpc_apicid, ++ mp_ioapics[idx].mpc_apicver, mp_ioapics[idx].mpc_apicaddr, ++ mp_ioapic_routing[idx].gsi_base, ++ mp_ioapic_routing[idx].gsi_end); ++ ++ return; ++} ++ ++ ++void __init mp_override_legacy_irq ( ++ u8 bus_irq, ++ u8 polarity, ++ u8 trigger, ++ u32 gsi) ++{ ++ struct mpc_config_intsrc intsrc; ++ int ioapic = -1; ++ int pin = -1; ++ ++ /* ++ * Convert 'gsi' to 'ioapic.pin'. ++ */ ++ ioapic = mp_find_ioapic(gsi); ++ if (ioapic < 0) ++ return; ++ pin = gsi - mp_ioapic_routing[ioapic].gsi_base; ++ ++ /* ++ * TBD: This check is for faulty timer entries, where the override ++ * erroneously sets the trigger to level, resulting in a HUGE ++ * increase of timer interrupts! ++ */ ++ if ((bus_irq == 0) && (trigger == 3)) ++ trigger = 1; ++ ++ intsrc.mpc_type = MP_INTSRC; ++ intsrc.mpc_irqtype = mp_INT; ++ intsrc.mpc_irqflag = (trigger << 2) | polarity; ++ intsrc.mpc_srcbus = MP_ISA_BUS; ++ intsrc.mpc_srcbusirq = bus_irq; /* IRQ */ ++ intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid; /* APIC ID */ ++ intsrc.mpc_dstirq = pin; /* INTIN# */ ++ ++ Dprintk("Int: type %d, pol %d, trig %d, bus %d, irq %d, %d-%d\n", ++ intsrc.mpc_irqtype, intsrc.mpc_irqflag & 3, ++ (intsrc.mpc_irqflag >> 2) & 3, intsrc.mpc_srcbus, ++ intsrc.mpc_srcbusirq, intsrc.mpc_dstapic, intsrc.mpc_dstirq); ++ ++ mp_irqs[mp_irq_entries] = intsrc; ++ if (++mp_irq_entries == MAX_IRQ_SOURCES) ++ panic("Max # of irq sources exceeded!\n"); ++ ++ return; ++} ++ ++void __init mp_config_acpi_legacy_irqs (void) ++{ ++ struct mpc_config_intsrc intsrc; ++ int i = 0; ++ int ioapic = -1; ++ ++ /* ++ * Fabricate the legacy ISA bus (bus #31). ++ */ ++ mp_bus_id_to_type[MP_ISA_BUS] = MP_BUS_ISA; ++ Dprintk("Bus #%d is ISA\n", MP_ISA_BUS); ++ ++ /* ++ * Older generations of ES7000 have no legacy identity mappings ++ */ ++ if (es7000_plat == 1) ++ return; ++ ++ /* ++ * Locate the IOAPIC that manages the ISA IRQs (0-15). ++ */ ++ ioapic = mp_find_ioapic(0); ++ if (ioapic < 0) ++ return; ++ ++ intsrc.mpc_type = MP_INTSRC; ++ intsrc.mpc_irqflag = 0; /* Conforming */ ++ intsrc.mpc_srcbus = MP_ISA_BUS; ++ intsrc.mpc_dstapic = mp_ioapics[ioapic].mpc_apicid; ++ ++ /* ++ * Use the default configuration for the IRQs 0-15. Unless ++ * overriden by (MADT) interrupt source override entries. ++ */ ++ for (i = 0; i < 16; i++) { ++ int idx; ++ ++ for (idx = 0; idx < mp_irq_entries; idx++) { ++ struct mpc_config_intsrc *irq = mp_irqs + idx; ++ ++ /* Do we already have a mapping for this ISA IRQ? */ ++ if (irq->mpc_srcbus == MP_ISA_BUS && irq->mpc_srcbusirq == i) ++ break; ++ ++ /* Do we already have a mapping for this IOAPIC pin */ ++ if ((irq->mpc_dstapic == intsrc.mpc_dstapic) && ++ (irq->mpc_dstirq == i)) ++ break; ++ } ++ ++ if (idx != mp_irq_entries) { ++ printk(KERN_DEBUG "ACPI: IRQ%d used by override.\n", i); ++ continue; /* IRQ already used */ ++ } ++ ++ intsrc.mpc_irqtype = mp_INT; ++ intsrc.mpc_srcbusirq = i; /* Identity mapped */ ++ intsrc.mpc_dstirq = i; ++ ++ Dprintk("Int: type %d, pol %d, trig %d, bus %d, irq %d, " ++ "%d-%d\n", intsrc.mpc_irqtype, intsrc.mpc_irqflag & 3, ++ (intsrc.mpc_irqflag >> 2) & 3, intsrc.mpc_srcbus, ++ intsrc.mpc_srcbusirq, intsrc.mpc_dstapic, ++ intsrc.mpc_dstirq); ++ ++ mp_irqs[mp_irq_entries] = intsrc; ++ if (++mp_irq_entries == MAX_IRQ_SOURCES) ++ panic("Max # of irq sources exceeded!\n"); ++ } ++} ++ ++#define MAX_GSI_NUM 4096 ++ ++int mp_register_gsi (u32 gsi, int triggering, int polarity) ++{ ++ int ioapic = -1; ++ int ioapic_pin = 0; ++ int idx, bit = 0; ++ static int pci_irq = 16; ++ /* ++ * Mapping between Global System Interrups, which ++ * represent all possible interrupts, and IRQs ++ * assigned to actual devices. ++ */ ++ static int gsi_to_irq[MAX_GSI_NUM]; ++ ++ /* Don't set up the ACPI SCI because it's already set up */ ++ if (acpi_fadt.sci_int == gsi) ++ return gsi; ++ ++ ioapic = mp_find_ioapic(gsi); ++ if (ioapic < 0) { ++ printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi); ++ return gsi; ++ } ++ ++ ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base; ++ ++ if (ioapic_renumber_irq) ++ gsi = ioapic_renumber_irq(ioapic, gsi); ++ ++ /* ++ * Avoid pin reprogramming. PRTs typically include entries ++ * with redundant pin->gsi mappings (but unique PCI devices); ++ * we only program the IOAPIC on the first. ++ */ ++ bit = ioapic_pin % 32; ++ idx = (ioapic_pin < 32) ? 0 : (ioapic_pin / 32); ++ if (idx > 3) { ++ printk(KERN_ERR "Invalid reference to IOAPIC pin " ++ "%d-%d\n", mp_ioapic_routing[ioapic].apic_id, ++ ioapic_pin); ++ return gsi; ++ } ++ if ((1< 15), but ++ * avoid a problem where the 8254 timer (IRQ0) is setup ++ * via an override (so it's not on pin 0 of the ioapic), ++ * and at the same time, the pin 0 interrupt is a PCI ++ * type. The gsi > 15 test could cause these two pins ++ * to be shared as IRQ0, and they are not shareable. ++ * So test for this condition, and if necessary, avoid ++ * the pin collision. ++ */ ++ if (gsi > 15 || (gsi == 0 && !timer_uses_ioapic_pin_0)) ++ gsi = pci_irq++; ++ /* ++ * Don't assign IRQ used by ACPI SCI ++ */ ++ if (gsi == acpi_fadt.sci_int) ++ gsi = pci_irq++; ++ gsi_to_irq[irq] = gsi; ++ } else { ++ printk(KERN_ERR "GSI %u is too high\n", gsi); ++ return gsi; ++ } ++ } ++ ++ io_apic_set_pci_routing(ioapic, ioapic_pin, gsi, ++ triggering == ACPI_EDGE_SENSITIVE ? 0 : 1, ++ polarity == ACPI_ACTIVE_HIGH ? 0 : 1); ++ return gsi; ++} ++ ++#endif /* CONFIG_X86_IO_APIC */ ++#endif /* CONFIG_ACPI */ +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/arch/x86/kernel/pci-dma-xen.c 2009-11-06 10:23:23.000000000 +0100 +@@ -0,0 +1,406 @@ ++/* ++ * Dynamic DMA mapping support. ++ * ++ * On i386 there is no hardware dynamic DMA address translation, ++ * so consistent alloc/free are merely page allocation/freeing. ++ * The rest of the dynamic DMA mapping interface is implemented ++ * in asm/pci.h. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef __x86_64__ ++#include ++ ++int iommu_merge __read_mostly = 0; ++EXPORT_SYMBOL(iommu_merge); ++ ++dma_addr_t bad_dma_address __read_mostly; ++EXPORT_SYMBOL(bad_dma_address); ++ ++/* This tells the BIO block layer to assume merging. Default to off ++ because we cannot guarantee merging later. */ ++int iommu_bio_merge __read_mostly = 0; ++EXPORT_SYMBOL(iommu_bio_merge); ++ ++int force_iommu __read_mostly= 0; ++ ++__init int iommu_setup(char *p) ++{ ++ return 1; ++} ++ ++void __init pci_iommu_alloc(void) ++{ ++#ifdef CONFIG_SWIOTLB ++ pci_swiotlb_init(); ++#endif ++} ++ ++static int __init pci_iommu_init(void) ++{ ++ no_iommu_init(); ++ return 0; ++} ++ ++/* Must execute after PCI subsystem */ ++fs_initcall(pci_iommu_init); ++#endif ++ ++struct dma_coherent_mem { ++ void *virt_base; ++ u32 device_base; ++ int size; ++ int flags; ++ unsigned long *bitmap; ++}; ++ ++#define IOMMU_BUG_ON(test) \ ++do { \ ++ if (unlikely(test)) { \ ++ printk(KERN_ALERT "Fatal DMA error! " \ ++ "Please use 'swiotlb=force'\n"); \ ++ BUG(); \ ++ } \ ++} while (0) ++ ++static int check_pages_physically_contiguous(unsigned long pfn, ++ unsigned int offset, ++ size_t length) ++{ ++ unsigned long next_mfn; ++ int i; ++ int nr_pages; ++ ++ next_mfn = pfn_to_mfn(pfn); ++ nr_pages = (offset + length + PAGE_SIZE-1) >> PAGE_SHIFT; ++ ++ for (i = 1; i < nr_pages; i++) { ++ if (pfn_to_mfn(++pfn) != ++next_mfn) ++ return 0; ++ } ++ return 1; ++} ++ ++int range_straddles_page_boundary(paddr_t p, size_t size) ++{ ++ unsigned long pfn = p >> PAGE_SHIFT; ++ unsigned int offset = p & ~PAGE_MASK; ++ ++ return ((offset + size > PAGE_SIZE) && ++ !check_pages_physically_contiguous(pfn, offset, size)); ++} ++ ++int ++dma_map_sg(struct device *hwdev, struct scatterlist *sg, int nents, ++ enum dma_data_direction direction) ++{ ++ int i, rc; ++ ++ if (direction == DMA_NONE) ++ BUG(); ++ WARN_ON(nents == 0 || sg[0].length == 0); ++ ++ if (swiotlb) { ++ rc = swiotlb_map_sg(hwdev, sg, nents, direction); ++ } else { ++ for (i = 0; i < nents; i++ ) { ++ BUG_ON(!sg[i].page); ++ sg[i].dma_address = ++ gnttab_dma_map_page(sg[i].page) + sg[i].offset; ++ sg[i].dma_length = sg[i].length; ++ IOMMU_BUG_ON(address_needs_mapping( ++ hwdev, sg[i].dma_address)); ++ IOMMU_BUG_ON(range_straddles_page_boundary( ++ page_to_pseudophys(sg[i].page) + sg[i].offset, ++ sg[i].length)); ++ } ++ rc = nents; ++ } ++ ++ flush_write_buffers(); ++ return rc; ++} ++EXPORT_SYMBOL(dma_map_sg); ++ ++void ++dma_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nents, ++ enum dma_data_direction direction) ++{ ++ int i; ++ ++ BUG_ON(direction == DMA_NONE); ++ if (swiotlb) ++ swiotlb_unmap_sg(hwdev, sg, nents, direction); ++ else { ++ for (i = 0; i < nents; i++ ) ++ gnttab_dma_unmap_page(sg[i].dma_address); ++ } ++} ++EXPORT_SYMBOL(dma_unmap_sg); ++ ++#ifdef CONFIG_HIGHMEM ++dma_addr_t ++dma_map_page(struct device *dev, struct page *page, unsigned long offset, ++ size_t size, enum dma_data_direction direction) ++{ ++ dma_addr_t dma_addr; ++ ++ BUG_ON(direction == DMA_NONE); ++ ++ if (swiotlb) { ++ dma_addr = swiotlb_map_page( ++ dev, page, offset, size, direction); ++ } else { ++ dma_addr = gnttab_dma_map_page(page) + offset; ++ IOMMU_BUG_ON(address_needs_mapping(dev, dma_addr)); ++ } ++ ++ return dma_addr; ++} ++EXPORT_SYMBOL(dma_map_page); ++ ++void ++dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size, ++ enum dma_data_direction direction) ++{ ++ BUG_ON(direction == DMA_NONE); ++ if (swiotlb) ++ swiotlb_unmap_page(dev, dma_address, size, direction); ++ else ++ gnttab_dma_unmap_page(dma_address); ++} ++EXPORT_SYMBOL(dma_unmap_page); ++#endif /* CONFIG_HIGHMEM */ ++ ++int ++dma_mapping_error(dma_addr_t dma_addr) ++{ ++ if (swiotlb) ++ return swiotlb_dma_mapping_error(dma_addr); ++ return 0; ++} ++EXPORT_SYMBOL(dma_mapping_error); ++ ++int ++dma_supported(struct device *dev, u64 mask) ++{ ++ if (swiotlb) ++ return swiotlb_dma_supported(dev, mask); ++ /* ++ * By default we'll BUG when an infeasible DMA is requested, and ++ * request swiotlb=force (see IOMMU_BUG_ON). ++ */ ++ return 1; ++} ++EXPORT_SYMBOL(dma_supported); ++ ++void *dma_alloc_coherent(struct device *dev, size_t size, ++ dma_addr_t *dma_handle, gfp_t gfp) ++{ ++ void *ret; ++ struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL; ++ unsigned int order = get_order(size); ++ unsigned long vstart; ++ u64 mask; ++ ++ /* ignore region specifiers */ ++ gfp &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32); ++ ++ if (mem) { ++ int page = bitmap_find_free_region(mem->bitmap, mem->size, ++ order); ++ if (page >= 0) { ++ *dma_handle = mem->device_base + (page << PAGE_SHIFT); ++ ret = mem->virt_base + (page << PAGE_SHIFT); ++ memset(ret, 0, size); ++ return ret; ++ } ++ if (mem->flags & DMA_MEMORY_EXCLUSIVE) ++ return NULL; ++ } ++ ++ vstart = __get_free_pages(gfp, order); ++ ret = (void *)vstart; ++ ++ if (dev != NULL && dev->coherent_dma_mask) ++ mask = dev->coherent_dma_mask; ++ else ++ mask = 0xffffffff; ++ ++ if (ret != NULL) { ++ if (xen_create_contiguous_region(vstart, order, ++ fls64(mask)) != 0) { ++ free_pages(vstart, order); ++ return NULL; ++ } ++ memset(ret, 0, size); ++ *dma_handle = virt_to_bus(ret); ++ } ++ return ret; ++} ++EXPORT_SYMBOL(dma_alloc_coherent); ++ ++void dma_free_coherent(struct device *dev, size_t size, ++ void *vaddr, dma_addr_t dma_handle) ++{ ++ struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL; ++ int order = get_order(size); ++ ++ if (mem && vaddr >= mem->virt_base && vaddr < (mem->virt_base + (mem->size << PAGE_SHIFT))) { ++ int page = (vaddr - mem->virt_base) >> PAGE_SHIFT; ++ ++ bitmap_release_region(mem->bitmap, page, order); ++ } else { ++ xen_destroy_contiguous_region((unsigned long)vaddr, order); ++ free_pages((unsigned long)vaddr, order); ++ } ++} ++EXPORT_SYMBOL(dma_free_coherent); ++ ++#ifdef ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY ++int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr, ++ dma_addr_t device_addr, size_t size, int flags) ++{ ++ void __iomem *mem_base; ++ int pages = size >> PAGE_SHIFT; ++ int bitmap_size = (pages + 31)/32; ++ ++ if ((flags & (DMA_MEMORY_MAP | DMA_MEMORY_IO)) == 0) ++ goto out; ++ if (!size) ++ goto out; ++ if (dev->dma_mem) ++ goto out; ++ ++ /* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */ ++ ++ mem_base = ioremap(bus_addr, size); ++ if (!mem_base) ++ goto out; ++ ++ dev->dma_mem = kmalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL); ++ if (!dev->dma_mem) ++ goto out; ++ memset(dev->dma_mem, 0, sizeof(struct dma_coherent_mem)); ++ dev->dma_mem->bitmap = kmalloc(bitmap_size, GFP_KERNEL); ++ if (!dev->dma_mem->bitmap) ++ goto free1_out; ++ memset(dev->dma_mem->bitmap, 0, bitmap_size); ++ ++ dev->dma_mem->virt_base = mem_base; ++ dev->dma_mem->device_base = device_addr; ++ dev->dma_mem->size = pages; ++ dev->dma_mem->flags = flags; ++ ++ if (flags & DMA_MEMORY_MAP) ++ return DMA_MEMORY_MAP; ++ ++ return DMA_MEMORY_IO; ++ ++ free1_out: ++ kfree(dev->dma_mem->bitmap); ++ out: ++ return 0; ++} ++EXPORT_SYMBOL(dma_declare_coherent_memory); ++ ++void dma_release_declared_memory(struct device *dev) ++{ ++ struct dma_coherent_mem *mem = dev->dma_mem; ++ ++ if(!mem) ++ return; ++ dev->dma_mem = NULL; ++ iounmap(mem->virt_base); ++ kfree(mem->bitmap); ++ kfree(mem); ++} ++EXPORT_SYMBOL(dma_release_declared_memory); ++ ++void *dma_mark_declared_memory_occupied(struct device *dev, ++ dma_addr_t device_addr, size_t size) ++{ ++ struct dma_coherent_mem *mem = dev->dma_mem; ++ int pages = (size + (device_addr & ~PAGE_MASK) + PAGE_SIZE - 1) >> PAGE_SHIFT; ++ int pos, err; ++ ++ if (!mem) ++ return ERR_PTR(-EINVAL); ++ ++ pos = (device_addr - mem->device_base) >> PAGE_SHIFT; ++ err = bitmap_allocate_region(mem->bitmap, pos, get_order(pages)); ++ if (err != 0) ++ return ERR_PTR(err); ++ return mem->virt_base + (pos << PAGE_SHIFT); ++} ++EXPORT_SYMBOL(dma_mark_declared_memory_occupied); ++#endif /* ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY */ ++ ++dma_addr_t ++dma_map_single(struct device *dev, void *ptr, size_t size, ++ enum dma_data_direction direction) ++{ ++ dma_addr_t dma; ++ ++ if (direction == DMA_NONE) ++ BUG(); ++ WARN_ON(size == 0); ++ ++ if (swiotlb) { ++ dma = swiotlb_map_single(dev, ptr, size, direction); ++ } else { ++ dma = gnttab_dma_map_page(virt_to_page(ptr)) + ++ offset_in_page(ptr); ++ IOMMU_BUG_ON(range_straddles_page_boundary(__pa(ptr), size)); ++ IOMMU_BUG_ON(address_needs_mapping(dev, dma)); ++ } ++ ++ flush_write_buffers(); ++ return dma; ++} ++EXPORT_SYMBOL(dma_map_single); ++ ++void ++dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, ++ enum dma_data_direction direction) ++{ ++ if (direction == DMA_NONE) ++ BUG(); ++ if (swiotlb) ++ swiotlb_unmap_single(dev, dma_addr, size, direction); ++ else ++ gnttab_dma_unmap_page(dma_addr); ++} ++EXPORT_SYMBOL(dma_unmap_single); ++ ++void ++dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size, ++ enum dma_data_direction direction) ++{ ++ if (swiotlb) ++ swiotlb_sync_single_for_cpu(dev, dma_handle, size, direction); ++} ++EXPORT_SYMBOL(dma_sync_single_for_cpu); ++ ++void ++dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size, ++ enum dma_data_direction direction) ++{ ++ if (swiotlb) ++ swiotlb_sync_single_for_device(dev, dma_handle, size, direction); ++} ++EXPORT_SYMBOL(dma_sync_single_for_device); +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/arch/x86/kernel/process_32-xen.c 2008-07-21 11:00:32.000000000 +0200 +@@ -0,0 +1,877 @@ ++/* ++ * linux/arch/i386/kernel/process.c ++ * ++ * Copyright (C) 1995 Linus Torvalds ++ * ++ * Pentium III FXSR, SSE support ++ * Gareth Hughes , May 2000 ++ */ ++ ++/* ++ * This file handles the architecture-dependent parts of process handling.. ++ */ ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#ifdef CONFIG_MATH_EMULATION ++#include ++#endif ++ ++#include ++#include ++#include ++ ++#include ++ ++#include ++#include ++ ++asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); ++ ++static int hlt_counter; ++ ++unsigned long boot_option_idle_override = 0; ++EXPORT_SYMBOL(boot_option_idle_override); ++ ++/* ++ * Return saved PC of a blocked thread. ++ */ ++unsigned long thread_saved_pc(struct task_struct *tsk) ++{ ++ return ((unsigned long *)tsk->thread.esp)[3]; ++} ++ ++/* ++ * Powermanagement idle function, if any.. ++ */ ++void (*pm_idle)(void); ++EXPORT_SYMBOL(pm_idle); ++static DEFINE_PER_CPU(unsigned int, cpu_idle_state); ++ ++void disable_hlt(void) ++{ ++ hlt_counter++; ++} ++ ++EXPORT_SYMBOL(disable_hlt); ++ ++void enable_hlt(void) ++{ ++ hlt_counter--; ++} ++ ++EXPORT_SYMBOL(enable_hlt); ++ ++/* ++ * On SMP it's slightly faster (but much more power-consuming!) ++ * to poll the ->work.need_resched flag instead of waiting for the ++ * cross-CPU IPI to arrive. Use this option with caution. ++ */ ++static void poll_idle (void) ++{ ++ local_irq_enable(); ++ ++ asm volatile( ++ "2:" ++ "testl %0, %1;" ++ "rep; nop;" ++ "je 2b;" ++ : : "i"(_TIF_NEED_RESCHED), "m" (current_thread_info()->flags)); ++} ++ ++static void xen_idle(void) ++{ ++ local_irq_disable(); ++ ++ if (need_resched()) ++ local_irq_enable(); ++ else { ++ current_thread_info()->status &= ~TS_POLLING; ++ smp_mb__after_clear_bit(); ++ safe_halt(); ++ current_thread_info()->status |= TS_POLLING; ++ } ++} ++#ifdef CONFIG_APM_MODULE ++EXPORT_SYMBOL(default_idle); ++#endif ++ ++#ifdef CONFIG_HOTPLUG_CPU ++extern cpumask_t cpu_initialized; ++static inline void play_dead(void) ++{ ++ idle_task_exit(); ++ local_irq_disable(); ++ cpu_clear(smp_processor_id(), cpu_initialized); ++ preempt_enable_no_resched(); ++ VOID(HYPERVISOR_vcpu_op(VCPUOP_down, smp_processor_id(), NULL)); ++ cpu_bringup(); ++} ++#else ++static inline void play_dead(void) ++{ ++ BUG(); ++} ++#endif /* CONFIG_HOTPLUG_CPU */ ++ ++/* ++ * The idle thread. There's no useful work to be ++ * done, so just try to conserve power and have a ++ * low exit latency (ie sit in a loop waiting for ++ * somebody to say that they'd like to reschedule) ++ */ ++void cpu_idle(void) ++{ ++ int cpu = smp_processor_id(); ++ ++ current_thread_info()->status |= TS_POLLING; ++ ++ /* endless idle loop with no priority at all */ ++ while (1) { ++ while (!need_resched()) { ++ void (*idle)(void); ++ ++ if (__get_cpu_var(cpu_idle_state)) ++ __get_cpu_var(cpu_idle_state) = 0; ++ ++ rmb(); ++ idle = xen_idle; /* no alternatives */ ++ ++ if (cpu_is_offline(cpu)) ++ play_dead(); ++ ++ __get_cpu_var(irq_stat).idle_timestamp = jiffies; ++ idle(); ++ } ++ preempt_enable_no_resched(); ++ schedule(); ++ preempt_disable(); ++ } ++} ++ ++void cpu_idle_wait(void) ++{ ++ unsigned int cpu, this_cpu = get_cpu(); ++ cpumask_t map; ++ ++ set_cpus_allowed(current, cpumask_of_cpu(this_cpu)); ++ put_cpu(); ++ ++ cpus_clear(map); ++ for_each_online_cpu(cpu) { ++ per_cpu(cpu_idle_state, cpu) = 1; ++ cpu_set(cpu, map); ++ } ++ ++ __get_cpu_var(cpu_idle_state) = 0; ++ ++ wmb(); ++ do { ++ ssleep(1); ++ for_each_online_cpu(cpu) { ++ if (cpu_isset(cpu, map) && !per_cpu(cpu_idle_state, cpu)) ++ cpu_clear(cpu, map); ++ } ++ cpus_and(map, map, cpu_online_map); ++ } while (!cpus_empty(map)); ++} ++EXPORT_SYMBOL_GPL(cpu_idle_wait); ++ ++void __devinit select_idle_routine(const struct cpuinfo_x86 *c) ++{ ++} ++ ++static int __init idle_setup (char *str) ++{ ++ if (!strncmp(str, "poll", 4)) { ++ printk("using polling idle threads.\n"); ++ pm_idle = poll_idle; ++ } ++ ++ boot_option_idle_override = 1; ++ return 1; ++} ++ ++__setup("idle=", idle_setup); ++ ++void show_regs(struct pt_regs * regs) ++{ ++ unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L; ++ ++ printk("\n"); ++ printk("Pid: %d, comm: %20s\n", current->pid, current->comm); ++ printk("EIP: %04x:[<%08lx>] CPU: %d\n",0xffff & regs->xcs,regs->eip, smp_processor_id()); ++ print_symbol("EIP is at %s\n", regs->eip); ++ ++ if (user_mode_vm(regs)) ++ printk(" ESP: %04x:%08lx",0xffff & regs->xss,regs->esp); ++ printk(" EFLAGS: %08lx %s (%s %.*s)\n", ++ regs->eflags, print_tainted(), system_utsname.release, ++ (int)strcspn(system_utsname.version, " "), ++ system_utsname.version); ++ printk("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n", ++ regs->eax,regs->ebx,regs->ecx,regs->edx); ++ printk("ESI: %08lx EDI: %08lx EBP: %08lx", ++ regs->esi, regs->edi, regs->ebp); ++ printk(" DS: %04x ES: %04x\n", ++ 0xffff & regs->xds,0xffff & regs->xes); ++ ++ cr0 = read_cr0(); ++ cr2 = read_cr2(); ++ cr3 = read_cr3(); ++ cr4 = read_cr4_safe(); ++ printk("CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n", cr0, cr2, cr3, cr4); ++ show_trace(NULL, regs, ®s->esp); ++} ++ ++/* ++ * This gets run with %ebx containing the ++ * function to call, and %edx containing ++ * the "args". ++ */ ++extern void kernel_thread_helper(void); ++__asm__(".section .text\n" ++ ".align 4\n" ++ "kernel_thread_helper:\n\t" ++ "movl %edx,%eax\n\t" ++ "pushl %edx\n\t" ++ "call *%ebx\n\t" ++ "pushl %eax\n\t" ++ "call do_exit\n" ++ ".previous"); ++ ++/* ++ * Create a kernel thread ++ */ ++int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) ++{ ++ struct pt_regs regs; ++ ++ memset(®s, 0, sizeof(regs)); ++ ++ regs.ebx = (unsigned long) fn; ++ regs.edx = (unsigned long) arg; ++ ++ regs.xds = __USER_DS; ++ regs.xes = __USER_DS; ++ regs.orig_eax = -1; ++ regs.eip = (unsigned long) kernel_thread_helper; ++ regs.xcs = GET_KERNEL_CS(); ++ regs.eflags = X86_EFLAGS_IF | X86_EFLAGS_SF | X86_EFLAGS_PF | 0x2; ++ ++ /* Ok, create the new process.. */ ++ return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); ++} ++EXPORT_SYMBOL(kernel_thread); ++ ++/* ++ * Free current thread data structures etc.. ++ */ ++void exit_thread(void) ++{ ++ /* The process may have allocated an io port bitmap... nuke it. */ ++ if (unlikely(test_thread_flag(TIF_IO_BITMAP))) { ++ struct task_struct *tsk = current; ++ struct thread_struct *t = &tsk->thread; ++ struct physdev_set_iobitmap set_iobitmap; ++ memset(&set_iobitmap, 0, sizeof(set_iobitmap)); ++ WARN_ON(HYPERVISOR_physdev_op(PHYSDEVOP_set_iobitmap, ++ &set_iobitmap)); ++ kfree(t->io_bitmap_ptr); ++ t->io_bitmap_ptr = NULL; ++ clear_thread_flag(TIF_IO_BITMAP); ++ } ++} ++ ++void flush_thread(void) ++{ ++ struct task_struct *tsk = current; ++ ++ memset(tsk->thread.debugreg, 0, sizeof(unsigned long)*8); ++ memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array)); ++ clear_tsk_thread_flag(tsk, TIF_DEBUG); ++ /* ++ * Forget coprocessor state.. ++ */ ++ clear_fpu(tsk); ++ clear_used_math(); ++} ++ ++void release_thread(struct task_struct *dead_task) ++{ ++ BUG_ON(dead_task->mm); ++ release_vm86_irqs(dead_task); ++} ++ ++/* ++ * This gets called before we allocate a new thread and copy ++ * the current task into it. ++ */ ++void prepare_to_copy(struct task_struct *tsk) ++{ ++ unlazy_fpu(tsk); ++} ++ ++int copy_thread(int nr, unsigned long clone_flags, unsigned long esp, ++ unsigned long unused, ++ struct task_struct * p, struct pt_regs * regs) ++{ ++ struct pt_regs * childregs; ++ struct task_struct *tsk; ++ int err; ++ ++ childregs = task_pt_regs(p); ++ *childregs = *regs; ++ childregs->eax = 0; ++ childregs->esp = esp; ++ ++ p->thread.esp = (unsigned long) childregs; ++ p->thread.esp0 = (unsigned long) (childregs+1); ++ ++ p->thread.eip = (unsigned long) ret_from_fork; ++ ++ savesegment(fs,p->thread.fs); ++ savesegment(gs,p->thread.gs); ++ ++ tsk = current; ++ if (unlikely(test_tsk_thread_flag(tsk, TIF_IO_BITMAP))) { ++ p->thread.io_bitmap_ptr = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL); ++ if (!p->thread.io_bitmap_ptr) { ++ p->thread.io_bitmap_max = 0; ++ return -ENOMEM; ++ } ++ memcpy(p->thread.io_bitmap_ptr, tsk->thread.io_bitmap_ptr, ++ IO_BITMAP_BYTES); ++ set_tsk_thread_flag(p, TIF_IO_BITMAP); ++ } ++ ++ /* ++ * Set a new TLS for the child thread? ++ */ ++ if (clone_flags & CLONE_SETTLS) { ++ struct desc_struct *desc; ++ struct user_desc info; ++ int idx; ++ ++ err = -EFAULT; ++ if (copy_from_user(&info, (void __user *)childregs->esi, sizeof(info))) ++ goto out; ++ err = -EINVAL; ++ if (LDT_empty(&info)) ++ goto out; ++ ++ idx = info.entry_number; ++ if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX) ++ goto out; ++ ++ desc = p->thread.tls_array + idx - GDT_ENTRY_TLS_MIN; ++ desc->a = LDT_entry_a(&info); ++ desc->b = LDT_entry_b(&info); ++ } ++ ++ p->thread.iopl = current->thread.iopl; ++ ++ err = 0; ++ out: ++ if (err && p->thread.io_bitmap_ptr) { ++ kfree(p->thread.io_bitmap_ptr); ++ p->thread.io_bitmap_max = 0; ++ } ++ return err; ++} ++ ++/* ++ * fill in the user structure for a core dump.. ++ */ ++void dump_thread(struct pt_regs * regs, struct user * dump) ++{ ++ int i; ++ ++/* changed the size calculations - should hopefully work better. lbt */ ++ dump->magic = CMAGIC; ++ dump->start_code = 0; ++ dump->start_stack = regs->esp & ~(PAGE_SIZE - 1); ++ dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT; ++ dump->u_dsize = ((unsigned long) (current->mm->brk + (PAGE_SIZE-1))) >> PAGE_SHIFT; ++ dump->u_dsize -= dump->u_tsize; ++ dump->u_ssize = 0; ++ for (i = 0; i < 8; i++) ++ dump->u_debugreg[i] = current->thread.debugreg[i]; ++ ++ if (dump->start_stack < TASK_SIZE) ++ dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT; ++ ++ dump->regs.ebx = regs->ebx; ++ dump->regs.ecx = regs->ecx; ++ dump->regs.edx = regs->edx; ++ dump->regs.esi = regs->esi; ++ dump->regs.edi = regs->edi; ++ dump->regs.ebp = regs->ebp; ++ dump->regs.eax = regs->eax; ++ dump->regs.ds = regs->xds; ++ dump->regs.es = regs->xes; ++ savesegment(fs,dump->regs.fs); ++ savesegment(gs,dump->regs.gs); ++ dump->regs.orig_eax = regs->orig_eax; ++ dump->regs.eip = regs->eip; ++ dump->regs.cs = regs->xcs; ++ dump->regs.eflags = regs->eflags; ++ dump->regs.esp = regs->esp; ++ dump->regs.ss = regs->xss; ++ ++ dump->u_fpvalid = dump_fpu (regs, &dump->i387); ++} ++EXPORT_SYMBOL(dump_thread); ++ ++/* ++ * Capture the user space registers if the task is not running (in user space) ++ */ ++int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs) ++{ ++ struct pt_regs ptregs = *task_pt_regs(tsk); ++ ptregs.xcs &= 0xffff; ++ ptregs.xds &= 0xffff; ++ ptregs.xes &= 0xffff; ++ ptregs.xss &= 0xffff; ++ ++ elf_core_copy_regs(regs, &ptregs); ++ ++ return 1; ++} ++ ++static noinline void __switch_to_xtra(struct task_struct *next_p) ++{ ++ struct thread_struct *next; ++ ++ next = &next_p->thread; ++ ++ if (test_tsk_thread_flag(next_p, TIF_DEBUG)) { ++ set_debugreg(next->debugreg[0], 0); ++ set_debugreg(next->debugreg[1], 1); ++ set_debugreg(next->debugreg[2], 2); ++ set_debugreg(next->debugreg[3], 3); ++ /* no 4 and 5 */ ++ set_debugreg(next->debugreg[6], 6); ++ set_debugreg(next->debugreg[7], 7); ++ } ++} ++ ++/* ++ * This function selects if the context switch from prev to next ++ * has to tweak the TSC disable bit in the cr4. ++ */ ++static inline void disable_tsc(struct task_struct *prev_p, ++ struct task_struct *next_p) ++{ ++ struct thread_info *prev, *next; ++ ++ /* ++ * gcc should eliminate the ->thread_info dereference if ++ * has_secure_computing returns 0 at compile time (SECCOMP=n). ++ */ ++ prev = task_thread_info(prev_p); ++ next = task_thread_info(next_p); ++ ++ if (has_secure_computing(prev) || has_secure_computing(next)) { ++ /* slow path here */ ++ if (has_secure_computing(prev) && ++ !has_secure_computing(next)) { ++ write_cr4(read_cr4() & ~X86_CR4_TSD); ++ } else if (!has_secure_computing(prev) && ++ has_secure_computing(next)) ++ write_cr4(read_cr4() | X86_CR4_TSD); ++ } ++} ++ ++/* ++ * switch_to(x,yn) should switch tasks from x to y. ++ * ++ * We fsave/fwait so that an exception goes off at the right time ++ * (as a call from the fsave or fwait in effect) rather than to ++ * the wrong process. Lazy FP saving no longer makes any sense ++ * with modern CPU's, and this simplifies a lot of things (SMP ++ * and UP become the same). ++ * ++ * NOTE! We used to use the x86 hardware context switching. The ++ * reason for not using it any more becomes apparent when you ++ * try to recover gracefully from saved state that is no longer ++ * valid (stale segment register values in particular). With the ++ * hardware task-switch, there is no way to fix up bad state in ++ * a reasonable manner. ++ * ++ * The fact that Intel documents the hardware task-switching to ++ * be slow is a fairly red herring - this code is not noticeably ++ * faster. However, there _is_ some room for improvement here, ++ * so the performance issues may eventually be a valid point. ++ * More important, however, is the fact that this allows us much ++ * more flexibility. ++ * ++ * The return value (in %eax) will be the "prev" task after ++ * the task-switch, and shows up in ret_from_fork in entry.S, ++ * for example. ++ */ ++struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct task_struct *next_p) ++{ ++ struct thread_struct *prev = &prev_p->thread, ++ *next = &next_p->thread; ++ int cpu = smp_processor_id(); ++#ifndef CONFIG_X86_NO_TSS ++ struct tss_struct *tss = &per_cpu(init_tss, cpu); ++#endif ++#if CONFIG_XEN_COMPAT > 0x030002 ++ struct physdev_set_iopl iopl_op; ++ struct physdev_set_iobitmap iobmp_op; ++#else ++ struct physdev_op _pdo[2], *pdo = _pdo; ++#define iopl_op pdo->u.set_iopl ++#define iobmp_op pdo->u.set_iobitmap ++#endif ++ multicall_entry_t _mcl[8], *mcl = _mcl; ++ ++ /* XEN NOTE: FS/GS saved in switch_mm(), not here. */ ++ ++ /* ++ * This is basically '__unlazy_fpu', except that we queue a ++ * multicall to indicate FPU task switch, rather than ++ * synchronously trapping to Xen. ++ */ ++ if (prev_p->thread_info->status & TS_USEDFPU) { ++ __save_init_fpu(prev_p); /* _not_ save_init_fpu() */ ++ mcl->op = __HYPERVISOR_fpu_taskswitch; ++ mcl->args[0] = 1; ++ mcl++; ++ } ++#if 0 /* lazy fpu sanity check */ ++ else BUG_ON(!(read_cr0() & 8)); ++#endif ++ ++ /* ++ * Reload esp0. ++ * This is load_esp0(tss, next) with a multicall. ++ */ ++ mcl->op = __HYPERVISOR_stack_switch; ++ mcl->args[0] = __KERNEL_DS; ++ mcl->args[1] = next->esp0; ++ mcl++; ++ ++ /* ++ * Load the per-thread Thread-Local Storage descriptor. ++ * This is load_TLS(next, cpu) with multicalls. ++ */ ++#define C(i) do { \ ++ if (unlikely(next->tls_array[i].a != prev->tls_array[i].a || \ ++ next->tls_array[i].b != prev->tls_array[i].b)) { \ ++ mcl->op = __HYPERVISOR_update_descriptor; \ ++ *(u64 *)&mcl->args[0] = virt_to_machine( \ ++ &get_cpu_gdt_table(cpu)[GDT_ENTRY_TLS_MIN + i]);\ ++ *(u64 *)&mcl->args[2] = *(u64 *)&next->tls_array[i]; \ ++ mcl++; \ ++ } \ ++} while (0) ++ C(0); C(1); C(2); ++#undef C ++ ++ if (unlikely(prev->iopl != next->iopl)) { ++ iopl_op.iopl = (next->iopl == 0) ? 1 : (next->iopl >> 12) & 3; ++#if CONFIG_XEN_COMPAT > 0x030002 ++ mcl->op = __HYPERVISOR_physdev_op; ++ mcl->args[0] = PHYSDEVOP_set_iopl; ++ mcl->args[1] = (unsigned long)&iopl_op; ++#else ++ mcl->op = __HYPERVISOR_physdev_op_compat; ++ pdo->cmd = PHYSDEVOP_set_iopl; ++ mcl->args[0] = (unsigned long)pdo++; ++#endif ++ mcl++; ++ } ++ ++ if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr)) { ++ set_xen_guest_handle(iobmp_op.bitmap, ++ (char *)next->io_bitmap_ptr); ++ iobmp_op.nr_ports = next->io_bitmap_ptr ? IO_BITMAP_BITS : 0; ++#if CONFIG_XEN_COMPAT > 0x030002 ++ mcl->op = __HYPERVISOR_physdev_op; ++ mcl->args[0] = PHYSDEVOP_set_iobitmap; ++ mcl->args[1] = (unsigned long)&iobmp_op; ++#else ++ mcl->op = __HYPERVISOR_physdev_op_compat; ++ pdo->cmd = PHYSDEVOP_set_iobitmap; ++ mcl->args[0] = (unsigned long)pdo++; ++#endif ++ mcl++; ++ } ++ ++#if CONFIG_XEN_COMPAT <= 0x030002 ++ BUG_ON(pdo > _pdo + ARRAY_SIZE(_pdo)); ++#endif ++ BUG_ON(mcl > _mcl + ARRAY_SIZE(_mcl)); ++ if (unlikely(HYPERVISOR_multicall_check(_mcl, mcl - _mcl, NULL))) ++ BUG(); ++ ++ /* ++ * Restore %fs and %gs if needed. ++ * ++ * Glibc normally makes %fs be zero, and %gs is one of ++ * the TLS segments. ++ */ ++ if (unlikely(next->fs)) ++ loadsegment(fs, next->fs); ++ ++ if (next->gs) ++ loadsegment(gs, next->gs); ++ ++ /* ++ * Now maybe handle debug registers ++ */ ++ if (unlikely(task_thread_info(next_p)->flags & _TIF_WORK_CTXSW)) ++ __switch_to_xtra(next_p); ++ ++ disable_tsc(prev_p, next_p); ++ ++ return prev_p; ++} ++ ++asmlinkage int sys_fork(struct pt_regs regs) ++{ ++ return do_fork(SIGCHLD, regs.esp, ®s, 0, NULL, NULL); ++} ++ ++asmlinkage int sys_clone(struct pt_regs regs) ++{ ++ unsigned long clone_flags; ++ unsigned long newsp; ++ int __user *parent_tidptr, *child_tidptr; ++ ++ clone_flags = regs.ebx; ++ newsp = regs.ecx; ++ parent_tidptr = (int __user *)regs.edx; ++ child_tidptr = (int __user *)regs.edi; ++ if (!newsp) ++ newsp = regs.esp; ++ return do_fork(clone_flags, newsp, ®s, 0, parent_tidptr, child_tidptr); ++} ++ ++/* ++ * This is trivial, and on the face of it looks like it ++ * could equally well be done in user mode. ++ * ++ * Not so, for quite unobvious reasons - register pressure. ++ * In user mode vfork() cannot have a stack frame, and if ++ * done by calling the "clone()" system call directly, you ++ * do not have enough call-clobbered registers to hold all ++ * the information you need. ++ */ ++asmlinkage int sys_vfork(struct pt_regs regs) ++{ ++ return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.esp, ®s, 0, NULL, NULL); ++} ++ ++/* ++ * sys_execve() executes a new program. ++ */ ++asmlinkage int sys_execve(struct pt_regs regs) ++{ ++ int error; ++ char * filename; ++ ++ filename = getname((char __user *) regs.ebx); ++ error = PTR_ERR(filename); ++ if (IS_ERR(filename)) ++ goto out; ++ error = do_execve(filename, ++ (char __user * __user *) regs.ecx, ++ (char __user * __user *) regs.edx, ++ ®s); ++ if (error == 0) { ++ task_lock(current); ++ current->ptrace &= ~PT_DTRACE; ++ task_unlock(current); ++ /* Make sure we don't return using sysenter.. */ ++ set_thread_flag(TIF_IRET); ++ } ++ putname(filename); ++out: ++ return error; ++} ++ ++#define top_esp (THREAD_SIZE - sizeof(unsigned long)) ++#define top_ebp (THREAD_SIZE - 2*sizeof(unsigned long)) ++ ++unsigned long get_wchan(struct task_struct *p) ++{ ++ unsigned long ebp, esp, eip; ++ unsigned long stack_page; ++ int count = 0; ++ if (!p || p == current || p->state == TASK_RUNNING) ++ return 0; ++ stack_page = (unsigned long)task_stack_page(p); ++ esp = p->thread.esp; ++ if (!stack_page || esp < stack_page || esp > top_esp+stack_page) ++ return 0; ++ /* include/asm-i386/system.h:switch_to() pushes ebp last. */ ++ ebp = *(unsigned long *) esp; ++ do { ++ if (ebp < stack_page || ebp > top_ebp+stack_page) ++ return 0; ++ eip = *(unsigned long *) (ebp+4); ++ if (!in_sched_functions(eip)) ++ return eip; ++ ebp = *(unsigned long *) ebp; ++ } while (count++ < 16); ++ return 0; ++} ++ ++/* ++ * sys_alloc_thread_area: get a yet unused TLS descriptor index. ++ */ ++static int get_free_idx(void) ++{ ++ struct thread_struct *t = ¤t->thread; ++ int idx; ++ ++ for (idx = 0; idx < GDT_ENTRY_TLS_ENTRIES; idx++) ++ if (desc_empty(t->tls_array + idx)) ++ return idx + GDT_ENTRY_TLS_MIN; ++ return -ESRCH; ++} ++ ++/* ++ * Set a given TLS descriptor: ++ */ ++asmlinkage int sys_set_thread_area(struct user_desc __user *u_info) ++{ ++ struct thread_struct *t = ¤t->thread; ++ struct user_desc info; ++ struct desc_struct *desc; ++ int cpu, idx; ++ ++ if (copy_from_user(&info, u_info, sizeof(info))) ++ return -EFAULT; ++ idx = info.entry_number; ++ ++ /* ++ * index -1 means the kernel should try to find and ++ * allocate an empty descriptor: ++ */ ++ if (idx == -1) { ++ idx = get_free_idx(); ++ if (idx < 0) ++ return idx; ++ if (put_user(idx, &u_info->entry_number)) ++ return -EFAULT; ++ } ++ ++ if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX) ++ return -EINVAL; ++ ++ desc = t->tls_array + idx - GDT_ENTRY_TLS_MIN; ++ ++ /* ++ * We must not get preempted while modifying the TLS. ++ */ ++ cpu = get_cpu(); ++ ++ if (LDT_empty(&info)) { ++ desc->a = 0; ++ desc->b = 0; ++ } else { ++ desc->a = LDT_entry_a(&info); ++ desc->b = LDT_entry_b(&info); ++ } ++ load_TLS(t, cpu); ++ ++ put_cpu(); ++ ++ return 0; ++} ++ ++/* ++ * Get the current Thread-Local Storage area: ++ */ ++ ++#define GET_BASE(desc) ( \ ++ (((desc)->a >> 16) & 0x0000ffff) | \ ++ (((desc)->b << 16) & 0x00ff0000) | \ ++ ( (desc)->b & 0xff000000) ) ++ ++#define GET_LIMIT(desc) ( \ ++ ((desc)->a & 0x0ffff) | \ ++ ((desc)->b & 0xf0000) ) ++ ++#define GET_32BIT(desc) (((desc)->b >> 22) & 1) ++#define GET_CONTENTS(desc) (((desc)->b >> 10) & 3) ++#define GET_WRITABLE(desc) (((desc)->b >> 9) & 1) ++#define GET_LIMIT_PAGES(desc) (((desc)->b >> 23) & 1) ++#define GET_PRESENT(desc) (((desc)->b >> 15) & 1) ++#define GET_USEABLE(desc) (((desc)->b >> 20) & 1) ++ ++asmlinkage int sys_get_thread_area(struct user_desc __user *u_info) ++{ ++ struct user_desc info; ++ struct desc_struct *desc; ++ int idx; ++ ++ if (get_user(idx, &u_info->entry_number)) ++ return -EFAULT; ++ if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX) ++ return -EINVAL; ++ ++ memset(&info, 0, sizeof(info)); ++ ++ desc = current->thread.tls_array + idx - GDT_ENTRY_TLS_MIN; ++ ++ info.entry_number = idx; ++ info.base_addr = GET_BASE(desc); ++ info.limit = GET_LIMIT(desc); ++ info.seg_32bit = GET_32BIT(desc); ++ info.contents = GET_CONTENTS(desc); ++ info.read_exec_only = !GET_WRITABLE(desc); ++ info.limit_in_pages = GET_LIMIT_PAGES(desc); ++ info.seg_not_present = !GET_PRESENT(desc); ++ info.useable = GET_USEABLE(desc); ++ ++ if (copy_to_user(u_info, &info, sizeof(info))) ++ return -EFAULT; ++ return 0; ++} ++ ++unsigned long arch_align_stack(unsigned long sp) ++{ ++ if (randomize_va_space) ++ sp -= get_random_int() % 8192; ++ return sp & ~0xf; ++} +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/arch/x86/kernel/quirks-xen.c 2008-01-28 12:24:19.000000000 +0100 +@@ -0,0 +1,47 @@ ++/* ++ * This file contains work-arounds for x86 and x86_64 platform bugs. ++ */ ++#include ++#include ++ ++#if defined(CONFIG_X86_IO_APIC) && (defined(CONFIG_SMP) || defined(CONFIG_XEN)) && defined(CONFIG_PCI) ++ ++static void __devinit quirk_intel_irqbalance(struct pci_dev *dev) ++{ ++ u8 config, rev; ++ u32 word; ++ ++ /* BIOS may enable hardware IRQ balancing for ++ * E7520/E7320/E7525(revision ID 0x9 and below) ++ * based platforms. ++ * Disable SW irqbalance/affinity on those platforms. ++ */ ++ pci_read_config_byte(dev, PCI_CLASS_REVISION, &rev); ++ if (rev > 0x9) ++ return; ++ ++ printk(KERN_INFO "Intel E7520/7320/7525 detected."); ++ ++ /* enable access to config space*/ ++ pci_read_config_byte(dev, 0xf4, &config); ++ pci_write_config_byte(dev, 0xf4, config|0x2); ++ ++ /* read xTPR register */ ++ raw_pci_ops->read(0, 0, 0x40, 0x4c, 2, &word); ++ ++ if (!(word & (1 << 13))) { ++ struct xen_platform_op op; ++ printk(KERN_INFO "Disabling irq balancing and affinity\n"); ++ op.cmd = XENPF_platform_quirk; ++ op.u.platform_quirk.quirk_id = QUIRK_NOIRQBALANCING; ++ WARN_ON(HYPERVISOR_platform_op(&op)); ++ } ++ ++ /* put back the original value for config space*/ ++ if (!(config & 0x2)) ++ pci_write_config_byte(dev, 0xf4, config); ++} ++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7320_MCH, quirk_intel_irqbalance); ++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7525_MCH, quirk_intel_irqbalance); ++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7520_MCH, quirk_intel_irqbalance); ++#endif +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ sle11sp1-2010-03-22/arch/x86/kernel/setup_32-xen.c 2008-04-22 15:41:51.000000000 +0200 +@@ -0,0 +1,1919 @@ ++/* ++ * linux/arch/i386/kernel/setup.c ++ * ++ * Copyright (C) 1995 Linus Torvalds ++ * ++ * Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999 ++ * ++ * Memory region support ++ * David Parsons , July-August 1999 ++ * ++ * Added E820 sanitization routine (removes overlapping memory regions); ++ * Brian Moyle , February 2001 ++ * ++ * Moved CPU detection code to cpu/${cpu}.c ++ * Patrick Mochel , March 2002 ++ * ++ * Provisions for empty E820 memory regions (reported by certain BIOSes). ++ * Alex Achenbach , December 2002. ++ * ++ */ ++ ++/* ++ * This file handles the architecture-dependent parts of initialization ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include